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

randombit / botan / 11330154854

14 Oct 2024 03:01PM UTC coverage: 91.085% (-0.04%) from 91.12%
11330154854

Pull #4291

github

web-flow
Merge d4ad4e5b5 into ed74c9542
Pull Request #4291: PQC: SLH-DSA

90252 of 99086 relevant lines covered (91.08%)

9324125.38 hits per line

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

84.77
/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 {
2✔
25
         BOTAN_UNUSED(config);
2✔
26
         return {""};
2✔
27
      }
28

29
      virtual std::string format_name(const std::string& alg, const std::string& param) const {
26✔
30
         return param.empty() ? alg : Botan::fmt("{}-{}", alg, param);
26✔
31
      }
32

33
      void go(const PerfConfig& config) override {
12✔
34
         const std::string alg = this->algo();
12✔
35
         const std::string padding = this->hash();
12✔
36

37
         const auto params = this->keygen_params(config);
12✔
38

39
         for(const auto& param : params) {
63✔
40
            const std::string nm = this->format_name(alg, param);
51✔
41
            bench_pk_sig(config, nm, alg, param, padding);
102✔
42
         }
51✔
43
      }
12✔
44

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

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

56
         auto key = keygen_timer->run([&] { return Botan::create_private_key(alg, rng, param); });
102✔
57
         ;
51✔
58

59
         if(key != nullptr) {
51✔
60
            config.record_result(*keygen_timer);
51✔
61

62
            std::vector<uint8_t> message, signature, bad_signature;
51✔
63

64
            Botan::PK_Signer sig(*key, rng, padding, Botan::Signature_Format::Standard, provider);
51✔
65
            Botan::PK_Verifier ver(*key, padding, Botan::Signature_Format::Standard, provider);
51✔
66

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

70
            size_t invalid_sigs = 0;
51✔
71

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

80
                  signature = sig_timer->run([&]() { return sig.sign_message(message, rng); });
222✔
81

82
                  bad_signature = signature;
111✔
83
                  bad_signature[rng.next_byte() % bad_signature.size()] ^= rng.next_nonzero_byte();
111✔
84
               }
85

86
               if(ver_timer->under(msec)) {
165✔
87
                  const bool verified = ver_timer->run([&] { return ver.verify_message(message, signature); });
232✔
88

89
                  if(!verified) {
116✔
90
                     invalid_sigs += 1;
×
91
                  }
92

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

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

101
            if(invalid_sigs > 0) {
51✔
102
               config.error_output() << invalid_sigs << " generated signatures rejected in " << nm
×
103
                                     << " signature bench\n";
×
104
            }
105

106
            config.record_result(*sig_timer);
51✔
107
            config.record_result(*ver_timer);
51✔
108
         }
51✔
109
      }
51✔
110
};
111

112
#endif
113

114
#if defined(BOTAN_HAS_DSA)
115

116
class PerfTest_DSA final : public PerfTest_PKSig {
1✔
117
   public:
118
      std::string algo() const override { return "DSA"; }
1✔
119

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

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

130
BOTAN_REGISTER_PERF_TEST("DSA", PerfTest_DSA);
1✔
131

132
#endif
133

134
#if defined(BOTAN_HAS_RSA)
135

136
class PerfTest_RSA final : public PerfTest_PKSig {
1✔
137
   public:
138
      std::string algo() const override { return "RSA"; }
1✔
139

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

142
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
143
         BOTAN_UNUSED(config);
1✔
144
         return {"1024", "2048", "3072", "4096"};
1✔
145
      }
146
};
147

148
BOTAN_REGISTER_PERF_TEST("RSA", PerfTest_RSA);
1✔
149

150
#endif
151

152
#if defined(BOTAN_HAS_ECDSA)
153

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

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

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

163
#endif
164

165
#if defined(BOTAN_HAS_ECKCDSA)
166

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

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

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

176
#endif
177

178
#if defined(BOTAN_HAS_ECGDSA)
179

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

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

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

189
#endif
190

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

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

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

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

205
BOTAN_REGISTER_PERF_TEST("GOST-34.10", PerfTest_Gost3410);
1✔
206

207
#endif
208

209
#if defined(BOTAN_HAS_SM2) && defined(BOTAN_HAS_SM3)
210

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

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

217
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
218
         BOTAN_UNUSED(config);
1✔
219
         return {"sm2p256v1"};
1✔
220
      }
221
};
222

223
BOTAN_REGISTER_PERF_TEST("SM2", PerfTest_SM2);
1✔
224

225
#endif
226

227
#if defined(BOTAN_HAS_ED25519)
228

229
class PerfTest_Ed25519 final : public PerfTest_PKSig {
1✔
230
   public:
231
      std::string algo() const override { return "Ed25519"; }
1✔
232

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

236
BOTAN_REGISTER_PERF_TEST("Ed25519", PerfTest_Ed25519);
1✔
237

238
#endif
239

240
#if defined(BOTAN_HAS_ED448)
241

242
class PerfTest_Ed448 final : public PerfTest_PKSig {
1✔
243
   public:
244
      std::string algo() const override { return "Ed448"; }
1✔
245

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

249
BOTAN_REGISTER_PERF_TEST("Ed448", PerfTest_Ed448);
1✔
250

251
#endif
252

253
#if defined(BOTAN_HAS_XMSS_RFC8391)
254

255
class PerfTest_XMSS final : public PerfTest_PKSig {
1✔
256
   public:
257
      std::string algo() const override { return "XMSS"; }
1✔
258

259
      std::string hash() const override { return ""; }
1✔
260

261
      std::string format_name(const std::string& alg, const std::string& param) const override {
4✔
262
         BOTAN_UNUSED(alg);
4✔
263
         return param;  // Param already has XMSS in the name...
4✔
264
      }
265

266
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
267
         BOTAN_UNUSED(config);
1✔
268

269
         /*
270
         We only test H10 signatures here since already they are quite slow (a
271
         few seconds per signature). On a fast machine, H16 signatures take 1-2
272
         minutes to generate and H20 signatures take 5-10 minutes to generate
273
         */
274
         return {
1✔
275
            "XMSS-SHA2_10_256",
276
            "XMSS-SHAKE_10_256",
277
            "XMSS-SHA2_10_512",
278
            "XMSS-SHAKE_10_512",
279
         };
1✔
280
      }
281
};
282

283
BOTAN_REGISTER_PERF_TEST("XMSS", PerfTest_XMSS);
1✔
284

285
#endif
286

287
#if defined(BOTAN_HAS_HSS_LMS)
288

289
class PerfTest_HSS_LMS final : public PerfTest_PKSig {
×
290
   public:
291
      std::string algo() const override { return "HSS-LMS"; }
×
292

293
      std::string hash() const override { return ""; }
×
294

295
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
×
296
         BOTAN_UNUSED(config);
×
297

298
         // At first we compare instances with multiple hash functions. LMS trees with
299
         // height 10 are suitable, since they can be used for enough signatures and are
300
         // fast enough for speed testing.
301
         // Afterward, setups with multiple HSS layers are tested
302
         return {"SHA-256,HW(10,1)",
×
303
                 "SHAKE-256(256),HW(10,1)",
304
                 "SHAKE-256(192),HW(10,1)",
305
                 "Truncated(SHA-256,192),HW(10,1)",
306
                 "SHA-256,HW(10,1),HW(10,1)",
307
                 "SHA-256,HW(10,1),HW(10,1),HW(10,1)"};
×
308
      }
309
};
310

311
BOTAN_REGISTER_PERF_TEST("HSS-LMS", PerfTest_HSS_LMS);
×
312

313
#endif
314

315
#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
316

317
class PerfTest_SPHINCSp final : public PerfTest_PKSig {
×
318
   public:
319
      std::string algo() const override { return "SPHINCS+"; }
×
320

321
      std::string hash() const override { return ""; }
×
322

323
      std::string format_name(const std::string& alg, const std::string& param) const override {
×
324
         BOTAN_UNUSED(alg);
×
325
         return param;  // Param already has algo in the string
×
326
      }
327

328
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
×
329
         BOTAN_UNUSED(config);
×
330

331
         return {"SphincsPlus-sha2-128s-r3.1",
×
332
                 "SphincsPlus-sha2-128f-r3.1",
333
                 "SphincsPlus-sha2-192s-r3.1",
334
                 "SphincsPlus-sha2-192f-r3.1",
335
                 "SphincsPlus-sha2-256s-r3.1",
336
                 "SphincsPlus-sha2-256f-r3.1",
337
                 "SphincsPlus-shake-128s-r3.1",
338
                 "SphincsPlus-shake-128f-r3.1",
339
                 "SphincsPlus-shake-192s-r3.1",
340
                 "SphincsPlus-shake-192f-r3.1",
341
                 "SphincsPlus-shake-256s-r3.1",
342
                 "SphincsPlus-shake-256f-r3.1"};
×
343
      }
344
};
345

346
BOTAN_REGISTER_PERF_TEST("SPHINCS+", PerfTest_SPHINCSp);
×
347

348
#endif
349

350
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
351

352
class PerfTest_SLH_DSA final : public PerfTest_PKSig {
1✔
353
   public:
354
      std::string algo() const override { return "SLH-DSA"; }
1✔
355

356
      std::string hash() const override { return ""; }
1✔
357

358
      std::string format_name(const std::string& alg, const std::string& param) const override {
12✔
359
         BOTAN_UNUSED(alg);
12✔
360
         return param;  // Param already has algo in the string
12✔
361
      }
362

363
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
364
         BOTAN_UNUSED(config);
1✔
365

366
         return {"SLH-DSA-SHA2-128s",
1✔
367
                 "SLH-DSA-SHA2-128f",
368
                 "SLH-DSA-SHA2-192s",
369
                 "SLH-DSA-SHA2-192f",
370
                 "SLH-DSA-SHA2-256s",
371
                 "SLH-DSA-SHA2-256f",
372
                 "SLH-DSA-SHAKE-128s",
373
                 "SLH-DSA-SHAKE-128f",
374
                 "SLH-DSA-SHAKE-192s",
375
                 "SLH-DSA-SHAKE-192f",
376
                 "SLH-DSA-SHAKE-256s",
377
                 "SLH-DSA-SHAKE-256f"};
1✔
378
      }
379
};
380

381
BOTAN_REGISTER_PERF_TEST("SLH-DSA", PerfTest_SLH_DSA);
1✔
382

383
#endif
384

385
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
386

387
class PerfTest_Dilithium final : public PerfTest_PKSig {
1✔
388
   public:
389
      std::string algo() const override { return "Dilithium"; }
1✔
390

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

393
      std::string format_name(const std::string& alg, const std::string& param) const override {
6✔
394
         BOTAN_UNUSED(alg);
6✔
395
         return param;  // Param already has algo in the string
6✔
396
      }
397

398
      std::vector<std::string> keygen_params(const PerfConfig& config) const override {
1✔
399
         BOTAN_UNUSED(config);
1✔
400

401
         return {
1✔
402
            "Dilithium-4x4-r3",
403
            "Dilithium-4x4-AES-r3",
404
            "Dilithium-6x5-r3",
405
            "Dilithium-6x5-AES-r3",
406
            "Dilithium-8x7-r3",
407
            "Dilithium-8x7-AES-r3",
408
         };
1✔
409
      }
410
};
411

412
BOTAN_REGISTER_PERF_TEST("Dilithium", PerfTest_Dilithium);
1✔
413

414
#endif
415

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