• 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

48.7
/src/cli/perf_misc.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
#include <cstring>
9

10
// Always available:
11
#include <botan/assert.h>
12
#include <botan/hex.h>
13
#include <botan/rng.h>
14
#include <botan/internal/fmt.h>
15

16
#if defined(BOTAN_HAS_BASE32_CODEC)
17
   #include <botan/base32.h>
18
#endif
19

20
#if defined(BOTAN_HAS_BASE58_CODEC)
21
   #include <botan/base58.h>
22
#endif
23

24
#if defined(BOTAN_HAS_BASE64_CODEC)
25
   #include <botan/base64.h>
26
#endif
27

28
#if defined(BOTAN_HAS_FPE_FE1)
29
   #include <botan/fpe_fe1.h>
30
#endif
31

32
#if defined(BOTAN_HAS_RFC3394_KEYWRAP)
33
   #include <botan/rfc3394.h>
34
#endif
35

36
#if defined(BOTAN_HAS_ZFEC)
37
   #include <botan/zfec.h>
38
#endif
39

40
namespace Botan_CLI {
41

42
namespace {
43

44
class PerfTest_Hex final : public PerfTest {
×
45
   public:
46
      void go(const PerfConfig& config) override {
×
47
         for(const size_t buf_size : config.buffer_sizes()) {
×
48
            std::vector<uint8_t> ibuf(buf_size);
×
49
            std::vector<uint8_t> rbuf(buf_size);
×
50
            const size_t olen = 2 * buf_size;
×
51

52
            auto enc_timer = config.make_timer("hex", ibuf.size(), "encode", "", ibuf.size());
×
53

54
            auto dec_timer = config.make_timer("hex", olen, "decode", "", olen);
×
55

56
            const auto msec = config.runtime();
×
57

58
            while(enc_timer->under(msec) && dec_timer->under(msec)) {
×
59
               config.rng().randomize(ibuf);
×
60

61
               std::string hex = enc_timer->run([&]() { return Botan::hex_encode(ibuf); });
×
62

63
               dec_timer->run([&]() { Botan::hex_decode(rbuf.data(), hex); });
×
64
               BOTAN_ASSERT(rbuf == ibuf, "Encode/decode round trip ok");
×
65
            }
×
66

67
            config.record_result(*enc_timer);
×
68
            config.record_result(*dec_timer);
×
69
         }
×
70
      }
×
71
};
72

73
BOTAN_REGISTER_PERF_TEST("hex", PerfTest_Hex);
×
74

75
#if defined(BOTAN_HAS_BASE32_CODEC)
76
class PerfTest_Base32 final : public PerfTest {
×
77
   public:
78
      void go(const PerfConfig& config) override {
×
79
         for(const size_t buf_size : config.buffer_sizes()) {
×
80
            std::vector<uint8_t> ibuf(buf_size);
×
81
            std::vector<uint8_t> rbuf(buf_size);
×
82
            const size_t olen = Botan::base32_encode_max_output(ibuf.size());
×
83

84
            auto enc_timer = config.make_timer("base32", ibuf.size(), "encode", "", ibuf.size());
×
85

86
            auto dec_timer = config.make_timer("base32", olen, "decode", "", olen);
×
87

88
            const auto msec = config.runtime();
×
89

90
            while(enc_timer->under(msec) && dec_timer->under(msec)) {
×
91
               config.rng().randomize(ibuf);
×
92

93
               std::string b32 = enc_timer->run([&]() { return Botan::base32_encode(ibuf); });
×
94

95
               dec_timer->run([&]() { Botan::base32_decode(rbuf.data(), b32); });
×
96
               BOTAN_ASSERT(rbuf == ibuf, "Encode/decode round trip ok");
×
97
            }
×
98

99
            config.record_result(*enc_timer);
×
100
            config.record_result(*dec_timer);
×
101
         }
×
102
      }
×
103
};
104

105
BOTAN_REGISTER_PERF_TEST("base32", PerfTest_Base32);
×
106

107
#endif
108

109
#if defined(BOTAN_HAS_BASE64_CODEC)
110
class PerfTest_Base64 final : public PerfTest {
×
111
   public:
112
      void go(const PerfConfig& config) override {
×
113
         for(const size_t buf_size : config.buffer_sizes()) {
×
114
            std::vector<uint8_t> ibuf(buf_size);
×
115
            std::vector<uint8_t> rbuf(buf_size);
×
116
            const size_t olen = Botan::base64_encode_max_output(ibuf.size());
×
117

118
            auto enc_timer = config.make_timer("base64", ibuf.size(), "encode", "", ibuf.size());
×
119

120
            auto dec_timer = config.make_timer("base64", olen, "decode", "", olen);
×
121

122
            const auto msec = config.runtime();
×
123

124
            while(enc_timer->under(msec) && dec_timer->under(msec)) {
×
125
               config.rng().randomize(ibuf);
×
126

127
               std::string b64 = enc_timer->run([&]() { return Botan::base64_encode(ibuf); });
×
128

129
               dec_timer->run([&]() { Botan::base64_decode(rbuf.data(), b64); });
×
130
               BOTAN_ASSERT(rbuf == ibuf, "Encode/decode round trip ok");
×
131
            }
×
132

133
            config.record_result(*enc_timer);
×
134
            config.record_result(*dec_timer);
×
135
         }
×
136
      }
×
137
};
138

139
BOTAN_REGISTER_PERF_TEST("base64", PerfTest_Base64);
×
140

141
#endif
142

143
#if defined(BOTAN_HAS_BASE58_CODEC)
144
class PerfTest_Base58 final : public PerfTest {
×
145
   public:
146
      void go(const PerfConfig& config) override {
×
147
         for(const size_t buf_size : config.buffer_sizes()) {
×
148
            std::vector<uint8_t> ibuf(buf_size);
×
149

150
            auto enc_timer = config.make_timer("base58", ibuf.size(), "encode", "", ibuf.size());
×
151
            auto dec_timer = config.make_timer("base58", ibuf.size(), "decode", "", ibuf.size());
×
152

153
            const auto msec = config.runtime();
×
154

155
            while(enc_timer->under(msec) && dec_timer->under(msec)) {
×
156
               config.rng().randomize(ibuf);
×
157

158
               const std::string b58 = enc_timer->run([&]() { return Botan::base58_encode(ibuf); });
×
159
               const auto rbuf = dec_timer->run([&] { return Botan::base58_decode(b58); });
×
160
               BOTAN_ASSERT(rbuf == ibuf, "Encode/decode round trip ok");
×
161
            }
×
162

163
            config.record_result(*enc_timer);
×
164
            config.record_result(*dec_timer);
×
165
         }
×
166
      }
×
167
};
168

169
BOTAN_REGISTER_PERF_TEST("base58", PerfTest_Base58);
×
170

171
#endif
172

173
#if defined(BOTAN_HAS_FPE_FE1)
174

175
class PerfTest_FpeFe1 final : public PerfTest {
1✔
176
   public:
177
      void go(const PerfConfig& config) override {
1✔
178
         const auto n = Botan::BigInt::from_u64(1000000000000000);
1✔
179

180
         auto enc_timer = config.make_timer("FPE_FE1 encrypt");
2✔
181
         auto dec_timer = config.make_timer("FPE_FE1 decrypt");
2✔
182

183
         const Botan::SymmetricKey key(config.rng(), 32);
1✔
184
         const std::vector<uint8_t> tweak(8);  // 8 zeros
1✔
185

186
         auto x = Botan::BigInt::one();
1✔
187

188
         Botan::FPE_FE1 fpe_fe1(n);
1✔
189
         fpe_fe1.set_key(key);
1✔
190

191
         auto runtime = config.runtime();
1✔
192

193
         while(enc_timer->under(runtime)) {
5✔
194
            enc_timer->start();
4✔
195
            x = fpe_fe1.encrypt(x, tweak.data(), tweak.size());
4✔
196
            enc_timer->stop();
4✔
197
         }
198
         config.record_result(*enc_timer);
1✔
199

200
         for(size_t i = 0; i != enc_timer->events(); ++i) {
5✔
201
            dec_timer->start();
4✔
202
            x = fpe_fe1.decrypt(x, tweak.data(), tweak.size());
4✔
203
            dec_timer->stop();
4✔
204
         }
205
         config.record_result(*dec_timer);
1✔
206

207
         BOTAN_ASSERT(x == 1, "FPE works");
1✔
208
      }
4✔
209
};
210

211
BOTAN_REGISTER_PERF_TEST("fpe_fe1", PerfTest_FpeFe1);
1✔
212

213
#endif
214

215
#if defined(BOTAN_HAS_RFC3394_KEYWRAP)
216
class PerfTest_Rfc3394 final : public PerfTest {
1✔
217
      void go(const PerfConfig& config) override {
1✔
218
         auto wrap_timer = config.make_timer("RFC3394 AES-256 key wrap");
2✔
219
         auto unwrap_timer = config.make_timer("RFC3394 AES-256 key unwrap");
2✔
220

221
         const Botan::SymmetricKey kek(config.rng(), 32);
1✔
222
         Botan::secure_vector<uint8_t> key(64, 0);
1✔
223

224
         const auto runtime = config.runtime();
1✔
225

226
         while(wrap_timer->under(runtime)) {
105✔
227
            wrap_timer->start();
104✔
228
            key = Botan::rfc3394_keywrap(key, kek);
208✔
229
            wrap_timer->stop();
104✔
230

231
            unwrap_timer->start();
104✔
232
            key = Botan::rfc3394_keyunwrap(key, kek);
208✔
233
            unwrap_timer->stop();
104✔
234

235
            key[0] += 1;
104✔
236
         }
237

238
         config.record_result(*wrap_timer);
1✔
239
         config.record_result(*unwrap_timer);
2✔
240
      }
3✔
241
};
242

243
BOTAN_REGISTER_PERF_TEST("rfc3394", PerfTest_Rfc3394);
1✔
244

245
#endif
246

247
#if defined(BOTAN_HAS_ZFEC)
248

249
class PerfTest_Zfec final : public PerfTest {
1✔
250
   public:
251
      void go(const PerfConfig& config) override {
1✔
252
         const size_t k = 4;
1✔
253
         const size_t n = 16;
1✔
254

255
         Botan::ZFEC zfec(k, n);
1✔
256

257
         const size_t share_size = 256 * 1024;
1✔
258

259
         std::vector<uint8_t> input(share_size * k);
1✔
260
         config.rng().randomize(input.data(), input.size());
1✔
261

262
         std::vector<uint8_t> output(share_size * n);
1✔
263

264
         auto enc_fn = [&](size_t share, const uint8_t buf[], size_t len) {
17✔
265
            std::memcpy(&output[share * share_size], buf, len);
16✔
266
         };
17✔
267

268
         const auto msec = config.runtime();
1✔
269

270
         const std::string alg = Botan::fmt("zfec {}/{}", k, n);
1✔
271

272
         auto enc_timer = config.make_timer(alg, input.size(), "encode", "", input.size());
1✔
273

274
         enc_timer->run_until_elapsed(msec, [&]() { zfec.encode(input.data(), input.size(), enc_fn); });
3✔
275

276
         config.record_result(*enc_timer);
1✔
277

278
         auto dec_timer = config.make_timer(alg, input.size(), "decode", "", input.size());
1✔
279

280
         std::map<size_t, const uint8_t*> shares;
1✔
281
         for(size_t i = 0; i != n; ++i) {
17✔
282
            shares[i] = &output[share_size * i];
16✔
283
         }
284

285
         // remove data shares to make decoding maximally expensive:
286
         while(shares.size() != k) {
13✔
287
            shares.erase(shares.begin());
12✔
288
         }
289

290
         std::vector<uint8_t> recovered(share_size * k);
1✔
291

292
         auto dec_fn = [&](size_t share, const uint8_t buf[], size_t len) {
5✔
293
            std::memcpy(&recovered[share * share_size], buf, len);
4✔
294
         };
5✔
295

296
         dec_timer->run_until_elapsed(msec, [&]() { zfec.decode_shares(shares, share_size, dec_fn); });
3✔
297

298
         config.record_result(*dec_timer);
1✔
299

300
         if(recovered != input) {
1✔
301
            config.error_output() << "ZFEC recovery failed\n";
×
302
         }
303
      }
4✔
304
};
305

306
BOTAN_REGISTER_PERF_TEST("zfec", PerfTest_Zfec);
1✔
307

308
#endif
309

310
}  // namespace
311

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