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

randombit / botan / 16736017941

04 Aug 2025 10:53PM UTC coverage: 90.674% (-0.006%) from 90.68%
16736017941

push

github

web-flow
Merge pull request #5036 from randombit/jack/clang-tidy-readability-implicit-bool-conversion

Enable clang-tidy warning readability-implict-bool-conversion

99981 of 110264 relevant lines covered (90.67%)

12208422.09 hits per line

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

92.75
/src/lib/ffi/ffi_pkey.cpp
1
/*
2
* (C) 2015,2017 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include <botan/ffi.h>
8

9
#include <botan/data_src.h>
10
#include <botan/hash.h>
11
#include <botan/pk_algs.h>
12
#include <botan/pk_keys.h>
13
#include <botan/pkcs8.h>
14
#include <botan/x509_key.h>
15
#include <botan/internal/ffi_ec.h>
16
#include <botan/internal/ffi_oid.h>
17
#include <botan/internal/ffi_pkey.h>
18
#include <botan/internal/ffi_rng.h>
19
#include <botan/internal/ffi_util.h>
20

21
#if defined(BOTAN_HAS_HASH_ID)
22
   #include <botan/internal/hash_id.h>
23
#endif
24

25
extern "C" {
26

27
using namespace Botan_FFI;
28

29
int botan_privkey_create(botan_privkey_t* key_obj,
85✔
30
                         const char* algo_name,
31
                         const char* algo_params,
32
                         botan_rng_t rng_obj) {
33
   // TODO(Botan4) remove this implicit algorithm choice and reject nullptr algo_name
34
   if(algo_name == nullptr) {
85✔
35
      return botan_privkey_create(key_obj, "RSA", algo_params, rng_obj);
36
   }
37

38
   return ffi_guard_thunk(__func__, [=]() -> int {
85✔
39
      if(key_obj == nullptr) {
85✔
40
         return BOTAN_FFI_ERROR_NULL_POINTER;
41
      }
42

43
      *key_obj = nullptr;
85✔
44
      if(rng_obj == nullptr) {
85✔
45
         return BOTAN_FFI_ERROR_NULL_POINTER;
46
      }
47

48
      const std::string params(algo_params != nullptr ? algo_params : "");
170✔
49

50
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
85✔
51

52
      if(auto key = Botan::create_private_key(algo_name, rng, params)) {
85✔
53
         return ffi_new_object(key_obj, std::move(key));
85✔
54
      } else {
55
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
56
      }
85✔
57
   });
85✔
58
}
59

60
int botan_ec_privkey_create(botan_privkey_t* key_obj,
2✔
61
                            const char* algo_name,
62
                            botan_ec_group_t ec_group_obj,
63
                            botan_rng_t rng_obj) {
64
   // TODO(Botan4) remove this implicit algorithm choice and reject nullptr algo_name
65
   if(algo_name == nullptr) {
2✔
66
      return botan_ec_privkey_create(key_obj, "ECDSA", ec_group_obj, rng_obj);
67
   }
68

69
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
70
      if(key_obj == nullptr) {
2✔
71
         return BOTAN_FFI_ERROR_NULL_POINTER;
72
      }
73
      *key_obj = nullptr;
2✔
74

75
      Botan::EC_Group ec_group = safe_get(ec_group_obj);
2✔
76
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
2✔
77

78
      if(auto key = Botan::create_ec_private_key(algo_name, ec_group, rng)) {
2✔
79
         return ffi_new_object(key_obj, std::move(key));
2✔
80
      } else {
81
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
82
      }
×
83
   });
2✔
84
}
85

86
int botan_privkey_load(
51✔
87
   botan_privkey_t* key, botan_rng_t rng_obj, const uint8_t bits[], size_t len, const char* password) {
88
   BOTAN_UNUSED(rng_obj);
51✔
89

90
   *key = nullptr;
51✔
91

92
   return ffi_guard_thunk(__func__, [=]() -> int {
51✔
93
      Botan::DataSource_Memory src(bits, len);
51✔
94

95
      std::unique_ptr<Botan::Private_Key> pkcs8;
51✔
96

97
      if(password == nullptr) {
51✔
98
         pkcs8 = Botan::PKCS8::load_key(src);
22✔
99
      } else {
100
         pkcs8 = Botan::PKCS8::load_key(src, std::string(password));
29✔
101
      }
102

103
      if(pkcs8) {
51✔
104
         ffi_new_object(key, std::move(pkcs8));
51✔
105
         return BOTAN_FFI_SUCCESS;
51✔
106
      }
107
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
108
   });
102✔
109
}
110

111
int botan_privkey_destroy(botan_privkey_t key) {
216✔
112
   return BOTAN_FFI_CHECKED_DELETE(key);
216✔
113
}
114

115
int botan_pubkey_load(botan_pubkey_t* key, const uint8_t bits[], size_t bits_len) {
12✔
116
   *key = nullptr;
12✔
117

118
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
119
      Botan::DataSource_Memory src(bits, bits_len);
12✔
120
      std::unique_ptr<Botan::Public_Key> pubkey(Botan::X509::load_key(src));
12✔
121

122
      if(pubkey == nullptr) {
12✔
123
         return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
124
      }
125

126
      ffi_new_object(key, std::move(pubkey));
12✔
127
      return BOTAN_FFI_SUCCESS;
12✔
128
   });
24✔
129
}
130

131
int botan_pubkey_destroy(botan_pubkey_t key) {
179✔
132
   return BOTAN_FFI_CHECKED_DELETE(key);
179✔
133
}
134

135
int botan_privkey_export_pubkey(botan_pubkey_t* pubout, botan_privkey_t key_obj) {
91✔
136
   return ffi_guard_thunk(__func__, [=]() -> int {
91✔
137
      auto public_key = safe_get(key_obj).public_key();
91✔
138
      ffi_new_object(pubout, std::move(public_key));
91✔
139
      return BOTAN_FFI_SUCCESS;
91✔
140
   });
91✔
141
}
142

143
int botan_privkey_algo_name(botan_privkey_t key, char out[], size_t* out_len) {
4✔
144
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { return write_str_output(out, out_len, k.algo_name()); });
8✔
145
}
146

147
int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len) {
7✔
148
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { return write_str_output(out, out_len, k.algo_name()); });
14✔
149
}
150

151
int botan_pubkey_check_key(botan_pubkey_t key, botan_rng_t rng, uint32_t flags) {
25✔
152
   const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS) != 0;
25✔
153

154
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
50✔
155
      return (k.check_key(safe_get(rng), strong) == true) ? 0 : BOTAN_FFI_ERROR_INVALID_INPUT;
156
   });
157
}
158

159
int botan_privkey_check_key(botan_privkey_t key, botan_rng_t rng, uint32_t flags) {
16✔
160
   const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS) != 0;
16✔
161
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
32✔
162
      return (k.check_key(safe_get(rng), strong) == true) ? 0 : BOTAN_FFI_ERROR_INVALID_INPUT;
163
   });
164
}
165

166
int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags) {
44✔
167
   if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
44✔
168
      return copy_view_bin(out, out_len, botan_pubkey_view_der, key);
22✔
169
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
22✔
170
      return copy_view_str(out, out_len, botan_pubkey_view_pem, key);
22✔
171
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_RAW) {
×
172
      return copy_view_bin(out, out_len, botan_pubkey_view_raw, key);
×
173
   } else {
174
      return BOTAN_FFI_ERROR_BAD_FLAG;
175
   }
176
}
177

178
int botan_pubkey_view_der(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
23✔
179
   return BOTAN_FFI_VISIT(
92✔
180
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, k.subject_public_key()); });
181
}
182

183
int botan_pubkey_view_pem(botan_pubkey_t key, botan_view_ctx ctx, botan_view_str_fn view) {
26✔
184
   return BOTAN_FFI_VISIT(
78✔
185
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, Botan::X509::PEM_encode(k)); });
186
}
187

188
int botan_pubkey_view_raw(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
110✔
189
   return BOTAN_FFI_VISIT(
438✔
190
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, k.raw_public_key_bits()); });
191
}
192

193
int botan_privkey_export(botan_privkey_t key, uint8_t out[], size_t* out_len, uint32_t flags) {
44✔
194
   if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
44✔
195
      return copy_view_bin(out, out_len, botan_privkey_view_der, key);
22✔
196
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
22✔
197
      return copy_view_str(out, out_len, botan_privkey_view_pem, key);
22✔
198
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_RAW) {
×
199
      return copy_view_bin(out, out_len, botan_privkey_view_raw, key);
×
200
   } else {
201
      return BOTAN_FFI_ERROR_BAD_FLAG;
202
   }
203
}
204

205
int botan_privkey_view_der(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
27✔
206
   return BOTAN_FFI_VISIT(key,
108✔
207
                          [=](const auto& k) -> int { return invoke_view_callback(view, ctx, k.private_key_info()); });
208
}
209

210
int botan_privkey_view_pem(botan_privkey_t key, botan_view_ctx ctx, botan_view_str_fn view) {
34✔
211
   return BOTAN_FFI_VISIT(
102✔
212
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, Botan::PKCS8::PEM_encode(k)); });
213
}
214

215
int botan_privkey_view_raw(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
110✔
216
   return BOTAN_FFI_VISIT(
438✔
217
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, k.raw_private_key_bits()); });
218
}
219

220
int botan_privkey_export_encrypted(botan_privkey_t key,
×
221
                                   uint8_t out[],
222
                                   size_t* out_len,
223
                                   botan_rng_t rng_obj,
224
                                   const char* pass,
225
                                   const char* /*ignored - pbe*/,
226
                                   uint32_t flags) {
227
   return botan_privkey_export_encrypted_pbkdf_iter(key, out, out_len, rng_obj, pass, 100000, nullptr, nullptr, flags);
×
228
}
229

230
int botan_privkey_export_encrypted_pbkdf_msec(botan_privkey_t key,
11✔
231
                                              uint8_t out[],
232
                                              size_t* out_len,
233
                                              botan_rng_t rng,
234
                                              const char* passphrase,
235
                                              uint32_t pbkdf_msec,
236
                                              size_t* pbkdf_iters_out,
237
                                              const char* cipher,
238
                                              const char* pbkdf_hash,
239
                                              uint32_t flags) {
240
   if(pbkdf_iters_out != nullptr) {
11✔
241
      *pbkdf_iters_out = 0;
11✔
242
   }
243

244
   if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
11✔
245
      return copy_view_bin(
11✔
246
         out, out_len, botan_privkey_view_encrypted_der_timed, key, rng, passphrase, cipher, pbkdf_hash, pbkdf_msec);
11✔
247
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
×
248
      return copy_view_str(
×
249
         out, out_len, botan_privkey_view_encrypted_pem_timed, key, rng, passphrase, cipher, pbkdf_hash, pbkdf_msec);
×
250
   } else {
251
      return BOTAN_FFI_ERROR_BAD_FLAG;
252
   }
253
}
254

255
int botan_privkey_view_encrypted_der_timed(botan_privkey_t key,
14✔
256
                                           botan_rng_t rng_obj,
257
                                           const char* passphrase,
258
                                           const char* maybe_cipher,
259
                                           const char* maybe_pbkdf_algo,
260
                                           size_t pbkdf_runtime_msec,
261
                                           botan_view_ctx ctx,
262
                                           botan_view_bin_fn view) {
263
   if(passphrase == nullptr) {
14✔
264
      return BOTAN_FFI_ERROR_NULL_POINTER;
265
   }
266

267
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
95✔
268
      const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
269
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
270

271
      const std::string cipher = (maybe_cipher ? maybe_cipher : "");
272
      const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
273

274
      auto pkcs8 =
275
         Botan::PKCS8::BER_encode_encrypted_pbkdf_msec(k, rng, passphrase, pbkdf_time, nullptr, cipher, pbkdf_algo);
276

277
      return invoke_view_callback(view, ctx, pkcs8);
278
   });
279
}
280

281
int botan_privkey_view_encrypted_pem_timed(botan_privkey_t key,
3✔
282
                                           botan_rng_t rng_obj,
283
                                           const char* passphrase,
284
                                           const char* maybe_cipher,
285
                                           const char* maybe_pbkdf_algo,
286
                                           size_t pbkdf_runtime_msec,
287
                                           botan_view_ctx ctx,
288
                                           botan_view_str_fn view) {
289
   if(passphrase == nullptr) {
3✔
290
      return BOTAN_FFI_ERROR_NULL_POINTER;
291
   }
292

293
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
15✔
294
      const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
295
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
296

297
      const std::string cipher = (maybe_cipher ? maybe_cipher : "");
298
      const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
299

300
      auto pkcs8 =
301
         Botan::PKCS8::PEM_encode_encrypted_pbkdf_msec(k, rng, passphrase, pbkdf_time, nullptr, cipher, pbkdf_algo);
302

303
      return invoke_view_callback(view, ctx, pkcs8);
304
   });
305
}
306

307
int botan_privkey_export_encrypted_pbkdf_iter(botan_privkey_t key,
44✔
308
                                              uint8_t out[],
309
                                              size_t* out_len,
310
                                              botan_rng_t rng,
311
                                              const char* passphrase,
312
                                              size_t pbkdf_iter,
313
                                              const char* cipher,
314
                                              const char* pbkdf_algo,
315
                                              uint32_t flags) {
316
   if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
44✔
317
      return copy_view_bin(
22✔
318
         out, out_len, botan_privkey_view_encrypted_der, key, rng, passphrase, cipher, pbkdf_algo, pbkdf_iter);
22✔
319
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
22✔
320
      return copy_view_str(
22✔
321
         out, out_len, botan_privkey_view_encrypted_pem, key, rng, passphrase, cipher, pbkdf_algo, pbkdf_iter);
22✔
322
   } else {
323
      return BOTAN_FFI_ERROR_BAD_FLAG;
324
   }
325
}
326

327
int botan_privkey_view_encrypted_der(botan_privkey_t key,
22✔
328
                                     botan_rng_t rng_obj,
329
                                     const char* passphrase,
330
                                     const char* maybe_cipher,
331
                                     const char* maybe_pbkdf_algo,
332
                                     size_t maybe_pbkdf_iterations,
333
                                     botan_view_ctx ctx,
334
                                     botan_view_bin_fn view) {
335
   if(passphrase == nullptr) {
22✔
336
      return BOTAN_FFI_ERROR_NULL_POINTER;
337
   }
338

339
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
176✔
340
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
341

342
      const std::string cipher = (maybe_cipher ? maybe_cipher : "");
343
      const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
344
      const size_t pbkdf_iter = (maybe_pbkdf_iterations ? maybe_pbkdf_iterations : 100000);
345

346
      auto pkcs8 = Botan::PKCS8::BER_encode_encrypted_pbkdf_iter(k, rng, passphrase, pbkdf_iter, cipher, pbkdf_algo);
347

348
      return invoke_view_callback(view, ctx, pkcs8);
349
   });
350
}
351

352
int botan_privkey_view_encrypted_pem(botan_privkey_t key,
22✔
353
                                     botan_rng_t rng_obj,
354
                                     const char* passphrase,
355
                                     const char* maybe_cipher,
356
                                     const char* maybe_pbkdf_algo,
357
                                     size_t maybe_pbkdf_iterations,
358
                                     botan_view_ctx ctx,
359
                                     botan_view_str_fn view) {
360
   if(passphrase == nullptr) {
22✔
361
      return BOTAN_FFI_ERROR_NULL_POINTER;
362
   }
363

364
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
154✔
365
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
366

367
      const std::string cipher = (maybe_cipher ? maybe_cipher : "");
368
      const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
369
      const size_t pbkdf_iter = (maybe_pbkdf_iterations ? maybe_pbkdf_iterations : 100000);
370

371
      auto pkcs8 = Botan::PKCS8::PEM_encode_encrypted_pbkdf_iter(k, rng, passphrase, pbkdf_iter, cipher, pbkdf_algo);
372

373
      return invoke_view_callback(view, ctx, pkcs8);
374
   });
375
}
376

377
int botan_pubkey_oid(botan_asn1_oid_t* oid, botan_pubkey_t key) {
2✔
378
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
379
      if(oid == nullptr) {
380
         return BOTAN_FFI_ERROR_NULL_POINTER;
381
      }
382

383
      auto oid_ptr = std::make_unique<Botan::OID>(k.object_identifier());
384
      ffi_new_object(oid, std::move(oid_ptr));
385

386
      return BOTAN_FFI_SUCCESS;
387
   });
388
}
389

390
int botan_privkey_oid(botan_asn1_oid_t* oid, botan_privkey_t key) {
2✔
391
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
392
      if(oid == nullptr) {
393
         return BOTAN_FFI_ERROR_NULL_POINTER;
394
      }
395

396
      auto oid_ptr = std::make_unique<Botan::OID>(k.object_identifier());
397
      ffi_new_object(oid, std::move(oid_ptr));
398

399
      return BOTAN_FFI_SUCCESS;
400
   });
401
}
402

403
int botan_privkey_stateful_operation(botan_privkey_t key, int* out) {
5✔
404
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
10✔
405
      if(out == nullptr) {
406
         return BOTAN_FFI_ERROR_NULL_POINTER;
407
      }
408

409
      if(k.stateful_operation()) {
410
         *out = 1;
411
      } else {
412
         *out = 0;
413
      }
414
      return BOTAN_FFI_SUCCESS;
415
   });
416
}
417

418
int botan_privkey_remaining_operations(botan_privkey_t key, uint64_t* out) {
5✔
419
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
10✔
420
      if(out == nullptr) {
421
         return BOTAN_FFI_ERROR_NULL_POINTER;
422
      }
423

424
      if(auto remaining = k.remaining_operations()) {
425
         *out = remaining.value();
426
         return BOTAN_FFI_SUCCESS;
427
      } else {
428
         return BOTAN_FFI_ERROR_NO_VALUE;
429
      }
430
   });
431
}
432

433
int botan_pubkey_estimated_strength(botan_pubkey_t key, size_t* estimate) {
14✔
434
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { *estimate = k.estimated_strength(); });
28✔
435
}
436

437
int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash_fn, uint8_t out[], size_t* out_len) {
22✔
438
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
110✔
439
      auto h = Botan::HashFunction::create_or_throw(hash_fn);
440
      return write_vec_output(out, out_len, h->process(k.public_key_bits()));
441
   });
442
}
443

444
int botan_pkcs_hash_id(const char* hash_name, uint8_t pkcs_id[], size_t* pkcs_id_len) {
2✔
445
#if defined(BOTAN_HAS_HASH_ID)
446
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
447
      const std::vector<uint8_t> hash_id = Botan::pkcs_hash_id(hash_name);
2✔
448
      return write_output(pkcs_id, pkcs_id_len, hash_id.data(), hash_id.size());
2✔
449
   });
2✔
450
#else
451
   BOTAN_UNUSED(hash_name, pkcs_id, pkcs_id_len);
452
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
453
#endif
454
}
455
}
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