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

randombit / botan / 21031897445

15 Jan 2026 12:50PM UTC coverage: 90.037% (-0.4%) from 90.395%
21031897445

Pull #5240

github

web-flow
Merge 13ffffdd5 into 32478179d
Pull Request #5240: Some changes to reduce time taken by the coverage build

102027 of 113317 relevant lines covered (90.04%)

11676540.94 hits per line

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

20.78
/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

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

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

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

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

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

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

38
namespace Botan_CLI {
39

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

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

50
            auto dec_timer = config.make_timer("hex", olen, "decode", "", olen);
×
51

52
            const auto msec = config.runtime();
×
53

54
            while(enc_timer->under(msec) && dec_timer->under(msec)) {
×
55
               config.rng().randomize(ibuf);
×
56

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

59
               dec_timer->run([&]() { Botan::hex_decode(rbuf.data(), hex); });
×
60
               BOTAN_ASSERT(rbuf == ibuf, "Encode/decode round trip ok");
×
61
            }
×
62

63
            config.record_result(*enc_timer);
×
64
            config.record_result(*dec_timer);
×
65
         }
×
66
      }
×
67
};
68

69
BOTAN_REGISTER_PERF_TEST("hex", PerfTest_Hex);
×
70

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

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

82
            auto dec_timer = config.make_timer("base32", olen, "decode", "", olen);
×
83

84
            const auto msec = config.runtime();
×
85

86
            while(enc_timer->under(msec) && dec_timer->under(msec)) {
×
87
               config.rng().randomize(ibuf);
×
88

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

91
               dec_timer->run([&]() { Botan::base32_decode(rbuf.data(), b32); });
×
92
               BOTAN_ASSERT(rbuf == ibuf, "Encode/decode round trip ok");
×
93
            }
×
94

95
            config.record_result(*enc_timer);
×
96
            config.record_result(*dec_timer);
×
97
         }
×
98
      }
×
99
};
100

101
BOTAN_REGISTER_PERF_TEST("base32", PerfTest_Base32);
×
102

103
#endif
104

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

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

116
            auto dec_timer = config.make_timer("base64", olen, "decode", "", olen);
×
117

118
            const auto msec = config.runtime();
×
119

120
            while(enc_timer->under(msec) && dec_timer->under(msec)) {
×
121
               config.rng().randomize(ibuf);
×
122

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

125
               dec_timer->run([&]() { Botan::base64_decode(rbuf.data(), b64); });
×
126
               BOTAN_ASSERT(rbuf == ibuf, "Encode/decode round trip ok");
×
127
            }
×
128

129
            config.record_result(*enc_timer);
×
130
            config.record_result(*dec_timer);
×
131
         }
×
132
      }
×
133
};
134

135
BOTAN_REGISTER_PERF_TEST("base64", PerfTest_Base64);
×
136

137
#endif
138

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

146
            auto enc_timer = config.make_timer("base58", ibuf.size(), "encode", "", ibuf.size());
×
147
            auto dec_timer = config.make_timer("base58", ibuf.size(), "decode", "", ibuf.size());
×
148

149
            const auto msec = config.runtime();
×
150

151
            while(enc_timer->under(msec) && dec_timer->under(msec)) {
×
152
               config.rng().randomize(ibuf);
×
153

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

159
            config.record_result(*enc_timer);
×
160
            config.record_result(*dec_timer);
×
161
         }
×
162
      }
×
163
};
164

165
BOTAN_REGISTER_PERF_TEST("base58", PerfTest_Base58);
×
166

167
#endif
168

169
#if defined(BOTAN_HAS_FPE_FE1)
170

171
class PerfTest_FpeFe1 final : public PerfTest {
×
172
   public:
173
      void go(const PerfConfig& config) override {
×
174
         const auto n = Botan::BigInt::from_u64(1000000000000000);
×
175

176
         auto enc_timer = config.make_timer("FPE_FE1 encrypt");
×
177
         auto dec_timer = config.make_timer("FPE_FE1 decrypt");
×
178

179
         const Botan::SymmetricKey key(config.rng(), 32);
×
180
         const std::vector<uint8_t> tweak(8);  // 8 zeros
×
181

182
         auto x = Botan::BigInt::one();
×
183

184
         Botan::FPE_FE1 fpe_fe1(n);
×
185
         fpe_fe1.set_key(key);
×
186

187
         auto runtime = config.runtime();
×
188

189
         while(enc_timer->under(runtime)) {
×
190
            enc_timer->start();
×
191
            x = fpe_fe1.encrypt(x, tweak.data(), tweak.size());
×
192
            enc_timer->stop();
×
193
         }
194
         config.record_result(*enc_timer);
×
195

196
         for(size_t i = 0; i != enc_timer->events(); ++i) {
×
197
            dec_timer->start();
×
198
            x = fpe_fe1.decrypt(x, tweak.data(), tweak.size());
×
199
            dec_timer->stop();
×
200
         }
201
         config.record_result(*dec_timer);
×
202

203
         BOTAN_ASSERT(x == 1, "FPE works");
×
204
      }
×
205
};
206

207
BOTAN_REGISTER_PERF_TEST("fpe_fe1", PerfTest_FpeFe1);
×
208

209
#endif
210

211
#if defined(BOTAN_HAS_RFC3394_KEYWRAP)
212
class PerfTest_Rfc3394 final : public PerfTest {
×
213
      void go(const PerfConfig& config) override {
×
214
         auto wrap_timer = config.make_timer("RFC3394 AES-256 key wrap");
×
215
         auto unwrap_timer = config.make_timer("RFC3394 AES-256 key unwrap");
×
216

217
         const Botan::SymmetricKey kek(config.rng(), 32);
×
218
         Botan::secure_vector<uint8_t> key(64, 0);
×
219

220
         const auto runtime = config.runtime();
×
221

222
         while(wrap_timer->under(runtime)) {
×
223
            wrap_timer->start();
×
224
            key = Botan::rfc3394_keywrap(key, kek);
×
225
            wrap_timer->stop();
×
226

227
            unwrap_timer->start();
×
228
            key = Botan::rfc3394_keyunwrap(key, kek);
×
229
            unwrap_timer->stop();
×
230

231
            key[0] += 1;
×
232
         }
233

234
         config.record_result(*wrap_timer);
×
235
         config.record_result(*unwrap_timer);
×
236
      }
×
237
};
238

239
BOTAN_REGISTER_PERF_TEST("rfc3394", PerfTest_Rfc3394);
×
240

241
#endif
242

243
#if defined(BOTAN_HAS_ZFEC)
244

245
class PerfTest_Zfec final : public PerfTest {
1✔
246
   public:
247
      void go(const PerfConfig& config) override {
1✔
248
         const size_t k = 4;
1✔
249
         const size_t n = 16;
1✔
250

251
         Botan::ZFEC zfec(k, n);
1✔
252

253
         const size_t share_size = 256 * 1024;
1✔
254

255
         std::vector<uint8_t> input(share_size * k);
1✔
256
         config.rng().randomize(input.data(), input.size());
1✔
257

258
         std::vector<uint8_t> output(share_size * n);
1✔
259

260
         auto enc_fn = [&](size_t share, const uint8_t buf[], size_t len) {
17✔
261
            std::memcpy(&output[share * share_size], buf, len);
16✔
262
         };
17✔
263

264
         const auto msec = config.runtime();
1✔
265

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

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

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

272
         config.record_result(*enc_timer);
1✔
273

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

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

281
         // remove data shares to make decoding maximally expensive:
282
         while(shares.size() != k) {
13✔
283
            shares.erase(shares.begin());
12✔
284
         }
285

286
         std::vector<uint8_t> recovered(share_size * k);
1✔
287

288
         auto dec_fn = [&](size_t share, const uint8_t buf[], size_t len) {
5✔
289
            std::memcpy(&recovered[share * share_size], buf, len);
4✔
290
         };
5✔
291

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

294
         config.record_result(*dec_timer);
1✔
295

296
         if(recovered != input) {
1✔
297
            config.error_output() << "ZFEC recovery failed\n";
×
298
         }
299
      }
4✔
300
};
301

302
BOTAN_REGISTER_PERF_TEST("zfec", PerfTest_Zfec);
1✔
303

304
#endif
305

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