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

randombit / botan / 13274522654

11 Feb 2025 11:26PM UTC coverage: 91.645% (-0.007%) from 91.652%
13274522654

push

github

web-flow
Merge pull request #4647 from randombit/jack/internal-assert-and-mem-ops

Avoid using mem_ops.h or assert.h in public headers

94854 of 103501 relevant lines covered (91.65%)

11334975.77 hits per line

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

80.0
/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
#endif
13

14
namespace Botan_CLI {
15

16
#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO)
17

18
class PerfTest_PKSig : public PerfTest {
12✔
19
   public:
20
      virtual std::string algo() const = 0;
21

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

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

26
      void go(const PerfConfig& config) override {
12✔
27
         const std::string alg = this->algo();
12✔
28
         const std::string padding = this->hash();
12✔
29

30
         const auto params = this->keygen_params(config);
12✔
31

32
         for(const auto& param : params) {
63✔
33
            const std::string nm = this->format_name(alg, param);
51✔
34
            bench_pk_sig(config, nm, alg, param, padding);
102✔
35
         }
51✔
36
      }
12✔
37

38
      void bench_pk_sig(const PerfConfig& config,
51✔
39
                        const std::string& nm,
40
                        const std::string& alg,
41
                        const std::string& param,
42
                        const std::string& padding,
43
                        const std::string& provider = "") {
44
         auto& rng = config.rng();
51✔
45
         const auto msec = config.runtime();
51✔
46

47
         auto keygen_timer = config.make_timer(nm, 1, "keygen");
102✔
48

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

51
         if(sk != nullptr) {
51✔
52
            while(keygen_timer->under(msec)) {
98✔
53
               sk = keygen_timer->run([&] { return Botan::create_private_key(alg, rng, param); });
141✔
54
            }
55

56
            config.record_result(*keygen_timer);
51✔
57

58
            auto pk = sk->public_key();
51✔
59

60
            std::vector<uint8_t> message, signature, bad_signature;
51✔
61

62
            Botan::PK_Signer sig(*sk, rng, padding, Botan::Signature_Format::Standard, provider);
51✔
63
            Botan::PK_Verifier ver(*pk, padding, Botan::Signature_Format::Standard, provider);
51✔
64

65
            auto sig_timer = config.make_timer(nm, 1, "sign");
102✔
66
            auto ver_timer = config.make_timer(nm, 1, "verify");
102✔
67

68
            size_t invalid_sigs = 0;
51✔
69

70
            while(ver_timer->under(msec) || sig_timer->under(msec)) {
275✔
71
               if(signature.empty() || sig_timer->under(msec)) {
173✔
72
                  /*
73
                  Length here is kind of arbitrary, but 48 bytes fits into a single
74
                  hash block so minimizes hashing overhead versus the PK op itself.
75
                  */
76
                  rng.random_vec(message, 48);
119✔
77

78
                  signature = sig_timer->run([&]() { return sig.sign_message(message, rng); });
238✔
79

80
                  bad_signature = signature;
119✔
81
                  bad_signature[rng.next_byte() % bad_signature.size()] ^= rng.next_nonzero_byte();
119✔
82
               }
83

84
               if(ver_timer->under(msec)) {
173✔
85
                  const bool verified = ver_timer->run([&] { return ver.verify_message(message, signature); });
236✔
86

87
                  if(!verified) {
118✔
88
                     invalid_sigs += 1;
×
89
                  }
90

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

93
                  if(verified_bad) {
118✔
94
                     config.error_output() << "Bad signature accepted in " << nm << " signature bench\n";
×
95
                  }
96
               }
97
            }
98

99
            if(invalid_sigs > 0) {
51✔
100
               config.error_output() << invalid_sigs << " generated signatures rejected in " << nm
×
101
                                     << " signature bench\n";
×
102
            }
103
            config.record_result(*sig_timer);
51✔
104
            config.record_result(*ver_timer);
102✔
105
         }
102✔
106
      }
51✔
107
};
108

109
#endif
110

111
#if defined(BOTAN_HAS_DSA)
112

113
class PerfTest_DSA final : public PerfTest_PKSig {
1✔
114
   public:
115
      std::string algo() const override { return "DSA"; }
1✔
116

117
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
1✔
118
         return {"dsa/jce/1024", "dsa/botan/2048", "dsa/botan/3072"};
1✔
119
      }
120

121
      std::string format_name(const std::string& alg, const std::string& param) const override {
3✔
122
         return Botan::fmt("{}-{}", alg, param.substr(param.find_last_of('/') + 1));
6✔
123
      }
124
};
125

126
BOTAN_REGISTER_PERF_TEST("DSA", PerfTest_DSA);
1✔
127

128
#endif
129

130
#if defined(BOTAN_HAS_RSA)
131

132
class PerfTest_RSA final : public PerfTest_PKSig {
1✔
133
   public:
134
      std::string algo() const override { return "RSA"; }
1✔
135

136
      std::string hash() const override { return "PKCS1v15(SHA-256)"; }
1✔
137

138
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
1✔
139
         return {"1024", "2048", "3072", "4096"};
1✔
140
      }
141
};
142

143
BOTAN_REGISTER_PERF_TEST("RSA", PerfTest_RSA);
1✔
144

145
#endif
146

147
#if defined(BOTAN_HAS_ECDSA)
148

149
class PerfTest_ECDSA final : public PerfTest_PKSig {
1✔
150
   public:
151
      std::string algo() const override { return "ECDSA"; }
1✔
152

153
      std::vector<std::string> keygen_params(const PerfConfig& config) const override { return config.ecc_groups(); }
1✔
154
};
155

156
BOTAN_REGISTER_PERF_TEST("ECDSA", PerfTest_ECDSA);
1✔
157

158
#endif
159

160
#if defined(BOTAN_HAS_ECKCDSA)
161

162
class PerfTest_ECKCDSA final : public PerfTest_PKSig {
1✔
163
   public:
164
      std::string algo() const override { return "ECKCDSA"; }
1✔
165

166
      std::vector<std::string> keygen_params(const PerfConfig& config) const override { return config.ecc_groups(); }
1✔
167
};
168

169
BOTAN_REGISTER_PERF_TEST("ECKCDSA", PerfTest_ECKCDSA);
1✔
170

171
#endif
172

173
#if defined(BOTAN_HAS_ECGDSA)
174

175
class PerfTest_ECGDSA final : public PerfTest_PKSig {
1✔
176
   public:
177
      std::string algo() const override { return "ECGDSA"; }
1✔
178

179
      std::vector<std::string> keygen_params(const PerfConfig& config) const override { return config.ecc_groups(); }
1✔
180
};
181

182
BOTAN_REGISTER_PERF_TEST("ECGDSA", PerfTest_ECGDSA);
1✔
183

184
#endif
185

186
#if defined(BOTAN_HAS_GOST_34_10_2001) && defined(BOTAN_HAS_GOST_34_11)
187

188
class PerfTest_Gost3410 final : public PerfTest_PKSig {
1✔
189
   public:
190
      std::string algo() const override { return "GOST-34.10"; }
1✔
191

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

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

197
BOTAN_REGISTER_PERF_TEST("GOST-34.10", PerfTest_Gost3410);
1✔
198

199
#endif
200

201
#if defined(BOTAN_HAS_SM2) && defined(BOTAN_HAS_SM3)
202

203
class PerfTest_SM2 final : public PerfTest_PKSig {
1✔
204
   public:
205
      std::string algo() const override { return "SM2"; }
1✔
206

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

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

212
BOTAN_REGISTER_PERF_TEST("SM2", PerfTest_SM2);
1✔
213

214
#endif
215

216
#if defined(BOTAN_HAS_ED25519)
217

218
class PerfTest_Ed25519 final : public PerfTest_PKSig {
1✔
219
   public:
220
      std::string algo() const override { return "Ed25519"; }
1✔
221

222
      std::string hash() const override { return "Pure"; }
1✔
223
};
224

225
BOTAN_REGISTER_PERF_TEST("Ed25519", PerfTest_Ed25519);
1✔
226

227
#endif
228

229
#if defined(BOTAN_HAS_ED448)
230

231
class PerfTest_Ed448 final : public PerfTest_PKSig {
1✔
232
   public:
233
      std::string algo() const override { return "Ed448"; }
1✔
234

235
      std::string hash() const override { return "Pure"; }
1✔
236
};
237

238
BOTAN_REGISTER_PERF_TEST("Ed448", PerfTest_Ed448);
1✔
239

240
#endif
241

242
#if defined(BOTAN_HAS_XMSS_RFC8391)
243

244
class PerfTest_XMSS final : public PerfTest_PKSig {
1✔
245
   public:
246
      std::string algo() const override { return "XMSS"; }
1✔
247

248
      std::string hash() const override { return ""; }
1✔
249

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

265
BOTAN_REGISTER_PERF_TEST("XMSS", PerfTest_XMSS);
1✔
266

267
#endif
268

269
#if defined(BOTAN_HAS_HSS_LMS)
270

271
class PerfTest_HSS_LMS final : public PerfTest_PKSig {
×
272
   public:
273
      std::string algo() const override { return "HSS-LMS"; }
×
274

275
      std::string hash() const override { return ""; }
×
276

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

291
BOTAN_REGISTER_PERF_TEST("HSS-LMS", PerfTest_HSS_LMS);
×
292

293
#endif
294

295
#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
296

297
class PerfTest_SPHINCSp final : public PerfTest_PKSig {
×
298
   public:
299
      std::string algo() const override { return "SPHINCS+"; }
×
300

301
      std::string hash() const override { return ""; }
×
302

303
      std::string format_name(const std::string& alg, const std::string& param) const override {
×
304
         return alg + param.substr(11);
×
305
      }
306

307
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
×
308
         return {"SphincsPlus-sha2-128s-r3.1",
×
309
                 "SphincsPlus-sha2-128f-r3.1",
310
                 "SphincsPlus-sha2-192s-r3.1",
311
                 "SphincsPlus-sha2-192f-r3.1",
312
                 "SphincsPlus-sha2-256s-r3.1",
313
                 "SphincsPlus-sha2-256f-r3.1",
314
                 "SphincsPlus-shake-128s-r3.1",
315
                 "SphincsPlus-shake-128f-r3.1",
316
                 "SphincsPlus-shake-192s-r3.1",
317
                 "SphincsPlus-shake-192f-r3.1",
318
                 "SphincsPlus-shake-256s-r3.1",
319
                 "SphincsPlus-shake-256f-r3.1"};
×
320
      }
321
};
322

323
BOTAN_REGISTER_PERF_TEST("SPHINCS+", PerfTest_SPHINCSp);
×
324

325
#endif
326

327
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
328

329
class PerfTest_SLH_DSA final : public PerfTest_PKSig {
1✔
330
   public:
331
      std::string algo() const override { return "SLH-DSA"; }
1✔
332

333
      std::string hash() const override { return ""; }
1✔
334

335
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
1✔
336
         return {"SLH-DSA-SHA2-128s",
1✔
337
                 "SLH-DSA-SHA2-128f",
338
                 "SLH-DSA-SHA2-192s",
339
                 "SLH-DSA-SHA2-192f",
340
                 "SLH-DSA-SHA2-256s",
341
                 "SLH-DSA-SHA2-256f",
342
                 "SLH-DSA-SHAKE-128s",
343
                 "SLH-DSA-SHAKE-128f",
344
                 "SLH-DSA-SHAKE-192s",
345
                 "SLH-DSA-SHAKE-192f",
346
                 "SLH-DSA-SHAKE-256s",
347
                 "SLH-DSA-SHAKE-256f"};
1✔
348
      }
349
};
350

351
BOTAN_REGISTER_PERF_TEST("SLH-DSA", PerfTest_SLH_DSA);
1✔
352

353
#endif
354

355
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
356

357
class PerfTest_Dilithium final : public PerfTest_PKSig {
1✔
358
   public:
359
      std::string algo() const override { return "Dilithium"; }
1✔
360

361
      std::string hash() const override { return ""; }
1✔
362

363
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
1✔
364
         return {
1✔
365
            "Dilithium-4x4-r3",
366
            "Dilithium-4x4-AES-r3",
367
            "Dilithium-6x5-r3",
368
            "Dilithium-6x5-AES-r3",
369
            "Dilithium-8x7-r3",
370
            "Dilithium-8x7-AES-r3",
371
         };
1✔
372
      }
373
};
374

375
BOTAN_REGISTER_PERF_TEST("Dilithium", PerfTest_Dilithium);
1✔
376

377
#endif
378

379
#if defined(BOTAN_HAS_ML_DSA)
380

381
class PerfTest_ML_DSA final : public PerfTest_PKSig {
×
382
   public:
383
      std::string algo() const override { return "ML-DSA"; }
×
384

385
      std::string hash() const override { return ""; }
×
386

387
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
×
388
         return {
×
389
            "ML-DSA-4x4",
390
            "ML-DSA-6x5",
391
            "ML-DSA-8x7",
392
         };
×
393
      }
394
};
395

396
BOTAN_REGISTER_PERF_TEST("ML-DSA", PerfTest_ML_DSA);
×
397

398
#endif
399

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