• 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

87.67
/src/cli/perf_sym.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
#include <botan/assert.h>
10
#include <set>
11

12
#include <botan/rng.h>
13
#include <botan/symkey.h>
14

15
#if defined(BOTAN_HAS_BLOCK_CIPHER)
16
   #include <botan/block_cipher.h>
17
#endif
18

19
#if defined(BOTAN_HAS_CIPHER_MODES)
20
   #include <botan/cipher_mode.h>
21
#endif
22

23
#if defined(BOTAN_HAS_STREAM_CIPHER)
24
   #include <botan/stream_cipher.h>
25
#endif
26

27
#if defined(BOTAN_HAS_HASH)
28
   #include <botan/hash.h>
29
#endif
30

31
#if defined(BOTAN_HAS_MAC)
32
   #include <botan/mac.h>
33
#endif
34

35
#if defined(BOTAN_HAS_XOF)
36
   #include <botan/xof.h>
37
#endif
38

39
namespace Botan_CLI {
40

41
namespace {
42

43
#if defined(BOTAN_HAS_BLOCK_CIPHER)
44
class PerfTest_BlockCipher final : public PerfTest {
45
   public:
46
      explicit PerfTest_BlockCipher(std::string_view alg) : m_alg(alg) {}
4✔
47

48
      void go(const PerfConfig& config) override {
4✔
49
         for(const auto& provider : Botan::BlockCipher::providers(m_alg)) {
8✔
50
            if(auto cipher = Botan::BlockCipher::create(m_alg, provider)) {
4✔
51
               bench_block_cipher(config, *cipher);
4✔
52
            }
4✔
53
         }
4✔
54
      }
4✔
55

56
      static bool has_impl_for(std::string_view alg) { return !Botan::BlockCipher::providers(alg).empty(); }
7✔
57

58
   private:
59
      static void bench_block_cipher(const PerfConfig& config, Botan::BlockCipher& cipher) {
4✔
60
         auto& rng = config.rng();
4✔
61
         const auto runtime = config.runtime();
4✔
62
         const auto provider = cipher.provider();
4✔
63

64
         auto ks_timer = config.make_timer(cipher.name(), 1, "key schedule", provider);
8✔
65

66
         const Botan::SymmetricKey key(rng, cipher.maximum_keylength());
4✔
67
         ks_timer->run([&]() { cipher.set_key(key); });
8✔
68

69
         const size_t bs = cipher.block_size();
4✔
70
         std::set<size_t> buf_sizes_in_blocks;
4✔
71
         for(const size_t buf_size : config.buffer_sizes()) {
9✔
72
            if(buf_size % bs == 0) {
5✔
73
               buf_sizes_in_blocks.insert(buf_size);
5✔
74
            } else {
75
               buf_sizes_in_blocks.insert(buf_size + bs - (buf_size % bs));
×
76
            }
77
         }
78

79
         for(const size_t buf_size : buf_sizes_in_blocks) {
9✔
80
            std::vector<uint8_t> buffer(buf_size);
5✔
81
            const size_t mult = std::max<size_t>(1, 65536 / buf_size);
5✔
82
            const size_t blocks = buf_size / bs;
5✔
83

84
            auto encrypt_timer = config.make_timer(cipher.name(), mult * buffer.size(), "encrypt", provider, buf_size);
10✔
85
            auto decrypt_timer = config.make_timer(cipher.name(), mult * buffer.size(), "decrypt", provider, buf_size);
10✔
86

87
            encrypt_timer->run_until_elapsed(runtime, [&]() {
5✔
88
               for(size_t i = 0; i != mult; ++i) {
17,873✔
89
                  cipher.encrypt_n(buffer.data(), buffer.data(), blocks);
17,792✔
90
               }
91
            });
81✔
92
            config.record_result(*encrypt_timer);
5✔
93

94
            decrypt_timer->run_until_elapsed(runtime, [&]() {
5✔
95
               for(size_t i = 0; i != mult; ++i) {
17,938✔
96
                  cipher.decrypt_n(buffer.data(), buffer.data(), blocks);
17,856✔
97
               }
98
            });
82✔
99
            config.record_result(*decrypt_timer);
10✔
100
         }
10✔
101
      }
8✔
102

103
      std::string m_alg;
104
};
105
#endif
106

107
#if defined(BOTAN_HAS_CIPHER_MODES)
108
class PerfTest_CipherMode final : public PerfTest {
109
   public:
110
      explicit PerfTest_CipherMode(std::string_view alg) : m_alg(alg) {}
1✔
111

112
      void go(const PerfConfig& config) override {
1✔
113
         for(const auto& provider : Botan::Cipher_Mode::providers(m_alg)) {
2✔
114
            if(auto enc = Botan::Cipher_Mode::create(m_alg, Botan::Cipher_Dir::Encryption, provider)) {
1✔
115
               auto dec = Botan::Cipher_Mode::create_or_throw(m_alg, Botan::Cipher_Dir::Decryption, provider);
1✔
116
               bench_cipher_mode(config, *enc, *dec);
1✔
117
            }
2✔
118
         }
1✔
119
      }
1✔
120

121
      static bool has_impl_for(std::string_view alg) { return !Botan::Cipher_Mode::providers(alg).empty(); }
3✔
122

123
   private:
124
      static void bench_cipher_mode(const PerfConfig& config, Botan::Cipher_Mode& enc, Botan::Cipher_Mode& dec) {
1✔
125
         auto& rng = config.rng();
1✔
126
         const auto runtime = config.runtime();
1✔
127
         const auto provider = enc.provider();
1✔
128

129
         auto ks_timer = config.make_timer(enc.name(), 1, "key schedule", provider);
2✔
130

131
         const Botan::SymmetricKey key(config.rng(), enc.key_spec().maximum_keylength());
1✔
132

133
         ks_timer->run([&]() { enc.set_key(key); });
2✔
134
         ks_timer->run([&]() { dec.set_key(key); });
2✔
135

136
         config.record_result(*ks_timer);
1✔
137

138
         for(auto buf_size : config.buffer_sizes()) {
2✔
139
            Botan::secure_vector<uint8_t> buffer = rng.random_vec(buf_size);
1✔
140
            const size_t mult = std::max<size_t>(1, 65536 / buf_size);
1✔
141

142
            auto encrypt_timer = config.make_timer(enc.name(), mult * buffer.size(), "encrypt", provider, buf_size);
2✔
143
            auto decrypt_timer = config.make_timer(dec.name(), mult * buffer.size(), "decrypt", provider, buf_size);
2✔
144

145
            Botan::secure_vector<uint8_t> iv = rng.random_vec(enc.default_nonce_length());
1✔
146

147
            if(buf_size >= enc.minimum_final_size()) {
1✔
148
               encrypt_timer->run_until_elapsed(runtime, [&]() {
1✔
149
                  for(size_t i = 0; i != mult; ++i) {
260✔
150
                     enc.start(iv);
256✔
151
                     enc.finish(buffer);
256✔
152
                     buffer.resize(buf_size);  // remove any tag or padding
256✔
153
                  }
154
               });
4✔
155

156
               Botan::secure_vector<uint8_t> dbuffer;
1✔
157

158
               size_t iter = 0;
1✔
159

160
               while(decrypt_timer->under(runtime)) {
5✔
161
                  if(iter == 0 || iter % 128 == 0) {
4✔
162
                     if(!iv.empty()) {
1✔
163
                        iv[iv.size() - 1] += 1;
1✔
164
                     }
165

166
                     // Create a valid ciphertext/tag for decryption to run on
167
                     buffer.resize(buf_size);
1✔
168
                     enc.start(iv);
1✔
169
                     enc.finish(buffer);
1✔
170
                  }
171

172
                  ++iter;
4✔
173

174
                  decrypt_timer->run([&]() {
4✔
175
                     for(size_t i = 0; i != mult; ++i) {
260✔
176
                        dbuffer = buffer;
256✔
177
                        dec.start(iv);
256✔
178
                        dec.finish(dbuffer);
512✔
179
                     }
180
                  });
4✔
181
               }
182
            }
1✔
183

184
            config.record_result(*encrypt_timer);
1✔
185
            config.record_result(*decrypt_timer);
2✔
186
         }
4✔
187
      }
1✔
188

189
      std::string m_alg;
190
};
191
#endif
192

193
#if defined(BOTAN_HAS_STREAM_CIPHER)
194
class PerfTest_StreamCipher final : public PerfTest {
195
   public:
196
      explicit PerfTest_StreamCipher(std::string_view alg) : m_alg(alg) {}
1✔
197

198
      void go(const PerfConfig& config) override {
1✔
199
         for(const auto& provider : Botan::StreamCipher::providers(m_alg)) {
2✔
200
            if(auto cipher = Botan::StreamCipher::create(m_alg, provider)) {
1✔
201
               bench_stream_cipher(config, *cipher);
1✔
202
            }
1✔
203
         }
1✔
204
      }
1✔
205

206
      static bool has_impl_for(std::string_view alg) { return !Botan::StreamCipher::providers(alg).empty(); }
8✔
207

208
   private:
209
      static void bench_stream_cipher(const PerfConfig& config, Botan::StreamCipher& cipher) {
1✔
210
         auto& rng = config.rng();
1✔
211
         const auto runtime = config.runtime();
1✔
212
         const auto provider = cipher.provider();
1✔
213

214
         for(auto buf_size : config.buffer_sizes()) {
2✔
215
            const Botan::SymmetricKey key(rng, cipher.maximum_keylength());
1✔
216
            cipher.set_key(key);
1✔
217

218
            if(cipher.valid_iv_length(12)) {
1✔
219
               const Botan::InitializationVector iv(rng, 12);
1✔
220
               cipher.set_iv(iv.begin(), iv.size());
1✔
221
            }
1✔
222

223
            auto buffer = rng.random_vec(buf_size);
1✔
224

225
            const size_t mult = std::max<size_t>(1, 65536 / buf_size);
1✔
226

227
            auto encrypt_timer = config.make_timer(cipher.name(), mult * buffer.size(), "encrypt", provider, buf_size);
2✔
228

229
            encrypt_timer->run_until_elapsed(runtime, [&]() {
1✔
230
               for(size_t i = 0; i != mult; ++i) {
910✔
231
                  cipher.encipher(buffer);
896✔
232
               }
233
            });
14✔
234

235
            config.record_result(*encrypt_timer);
1✔
236

237
            auto ks_timer =
1✔
238
               config.make_timer(cipher.name(), mult * buffer.size(), "write_keystream", provider, buf_size);
2✔
239

240
            while(ks_timer->under(runtime)) {
28✔
241
               ks_timer->run([&]() {
27✔
242
                  for(size_t i = 0; i != mult; ++i) {
1,755✔
243
                     cipher.write_keystream(buffer.data(), buffer.size());
1,728✔
244
                  }
245
               });
27✔
246
            }
247

248
            config.record_result(*ks_timer);
2✔
249
         }
3✔
250
      }
1✔
251

252
      std::string m_alg;
253
};
254
#endif
255

256
#if defined(BOTAN_HAS_HASH)
257
class PerfTest_HashFunction final : public PerfTest {
258
   public:
259
      explicit PerfTest_HashFunction(std::string_view alg) : m_alg(alg) {}
1✔
260

261
      void go(const PerfConfig& config) override {
1✔
262
         for(const auto& provider : Botan::HashFunction::providers(m_alg)) {
2✔
263
            if(auto hash = Botan::HashFunction::create(m_alg, provider)) {
1✔
264
               bench_hash_fn(config, *hash);
1✔
265
            }
1✔
266
         }
1✔
267
      }
1✔
268

269
      static bool has_impl_for(std::string_view alg) { return !Botan::HashFunction::providers(alg).empty(); }
2✔
270

271
   private:
272
      static void bench_hash_fn(const PerfConfig& config, Botan::HashFunction& hash) {
1✔
273
         std::vector<uint8_t> output(hash.output_length());
1✔
274
         const auto provider = hash.provider();
1✔
275
         const auto runtime = config.runtime();
1✔
276

277
         for(auto buf_size : config.buffer_sizes()) {
2✔
278
            const auto buffer = config.rng().random_vec(buf_size);
1✔
279

280
            const size_t mult = std::max<size_t>(1, 65536 / buf_size);
1✔
281

282
            auto timer = config.make_timer(hash.name(), mult * buffer.size(), "hash", provider, buf_size);
2✔
283
            timer->run_until_elapsed(runtime, [&]() {
1✔
284
               for(size_t i = 0; i != mult; ++i) {
325✔
285
                  hash.update(buffer);
320✔
286
                  hash.final(output.data());
640✔
287
               }
288
            });
5✔
289
            config.record_result(*timer);
2✔
290
         }
2✔
291
      }
2✔
292

293
      std::string m_alg;
294
};
295
#endif
296

297
#if defined(BOTAN_HAS_MAC)
298
class PerfTest_MessageAuthenticationCode final : public PerfTest {
299
   public:
300
      explicit PerfTest_MessageAuthenticationCode(std::string_view alg) : m_alg(alg) {}
1✔
301

302
      void go(const PerfConfig& config) override {
1✔
303
         for(const auto& provider : Botan::MessageAuthenticationCode::providers(m_alg)) {
2✔
304
            if(auto mac = Botan::MessageAuthenticationCode::create(m_alg, provider)) {
1✔
305
               bench_mac_fn(config, *mac);
1✔
306
            }
1✔
307
         }
1✔
308
      }
1✔
309

310
      static bool has_impl_for(std::string_view alg) {
1✔
311
         return !Botan::MessageAuthenticationCode::providers(alg).empty();
1✔
312
      }
313

314
   private:
315
      static void bench_mac_fn(const PerfConfig& config, Botan::MessageAuthenticationCode& mac) {
1✔
316
         std::vector<uint8_t> output(mac.output_length());
1✔
317
         const auto provider = mac.provider();
1✔
318
         const auto runtime = config.runtime();
1✔
319
         auto& rng = config.rng();
1✔
320

321
         for(auto buf_size : config.buffer_sizes()) {
2✔
322
            Botan::secure_vector<uint8_t> buffer = rng.random_vec(buf_size);
1✔
323
            const size_t mult = std::max<size_t>(1, 65536 / buf_size);
1✔
324

325
            const Botan::SymmetricKey key(rng, mac.maximum_keylength());
1✔
326
            mac.set_key(key);
1✔
327

328
            auto timer = config.make_timer(mac.name(), mult * buffer.size(), "mac", provider, buf_size);
2✔
329
            timer->run_until_elapsed(runtime, [&]() {
1✔
330
               for(size_t i = 0; i != mult; ++i) {
260✔
331
                  if(mac.fresh_key_required_per_message()) {
256✔
332
                     mac.set_key(key);
×
333
                  }
334
                  mac.start(nullptr, 0);
256✔
335
                  mac.update(buffer);
256✔
336
                  mac.final(output.data());
512✔
337
               }
338
            });
4✔
339

340
            config.record_result(*timer);
2✔
341
         }
3✔
342
      }
2✔
343

344
      std::string m_alg;
345
};
346
#endif
347

348
#if defined(BOTAN_HAS_XOF)
349
class PerfTest_XOF final : public PerfTest {
350
   public:
351
      explicit PerfTest_XOF(std::string_view alg) : m_alg(alg) {}
×
352

353
      void go(const PerfConfig& config) override {
×
354
         for(const auto& provider : Botan::XOF::providers(m_alg)) {
×
355
            if(auto xof = Botan::XOF::create(m_alg, provider)) {
×
356
               bench_xof_fn(config, *xof);
×
357
            }
×
358
         }
×
359
      }
×
360

361
      static bool has_impl_for(std::string_view alg) { return !Botan::XOF::providers(alg).empty(); }
8✔
362

363
   private:
364
      static void bench_xof_fn(const PerfConfig& config, Botan::XOF& xof) {
×
365
         const auto runtime = config.runtime();
×
366
         const auto provider = xof.provider();
×
367

368
         for(const size_t buf_size : config.buffer_sizes()) {
×
369
            auto in = config.rng().random_vec(buf_size);
×
370
            Botan::secure_vector<uint8_t> out(buf_size);
×
371

372
            auto in_timer = config.make_timer(xof.name(), in.size(), "input", provider, buf_size);
×
373
            in_timer->run_until_elapsed(runtime / 2, [&]() { xof.update(in); });
×
374

375
            auto out_timer = config.make_timer(xof.name(), out.size(), "output", provider, buf_size);
×
376
            out_timer->run_until_elapsed(runtime / 2, [&] { xof.output(out); });
×
377

378
            config.record_result(*in_timer);
×
379
            config.record_result(*out_timer);
×
380

381
            // Our XOFs don't want to consume inputs after producing output, so reset the state
382
            xof.clear();
×
383
         }
×
384
      }
×
385

386
      std::string m_alg;
387
};
388
#endif
389

390
}  // namespace
391

392
//static
393
std::unique_ptr<PerfTest> PerfTest::get_sym(const std::string& alg) {
8✔
394
#if defined(BOTAN_HAS_XOF)
395
   if(PerfTest_XOF::has_impl_for(alg)) {
8✔
396
      return std::make_unique<PerfTest_XOF>(alg);
×
397
   }
398
#endif
399

400
#if defined(BOTAN_HAS_STREAM_CIPHER)
401
   if(PerfTest_StreamCipher::has_impl_for(alg)) {
8✔
402
      return std::make_unique<PerfTest_StreamCipher>(alg);
1✔
403
   }
404
#endif
405

406
#if defined(BOTAN_HAS_BLOCK_CIPHER)
407
   if(PerfTest_BlockCipher::has_impl_for(alg)) {
7✔
408
      return std::make_unique<PerfTest_BlockCipher>(alg);
4✔
409
   }
410
#endif
411

412
#if defined(BOTAN_HAS_CIPHER_MODES)
413
   if(PerfTest_CipherMode::has_impl_for(alg)) {
3✔
414
      return std::make_unique<PerfTest_CipherMode>(alg);
1✔
415
   }
416
#endif
417

418
#if defined(BOTAN_HAS_HASH)
419
   if(PerfTest_HashFunction::has_impl_for(alg)) {
2✔
420
      return std::make_unique<PerfTest_HashFunction>(alg);
1✔
421
   }
422
#endif
423

424
#if defined(BOTAN_HAS_MAC)
425
   if(PerfTest_MessageAuthenticationCode::has_impl_for(alg)) {
1✔
426
      return std::make_unique<PerfTest_MessageAuthenticationCode>(alg);
1✔
427
   }
428
#endif
429

430
   BOTAN_UNUSED(alg);
×
431
   return {};
×
432
}
433

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