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

randombit / botan / 14571729020

21 Apr 2025 10:08AM UTC coverage: 91.511% (+0.2%) from 91.313%
14571729020

push

github

web-flow
Merge pull request #4816 from arckoor/oid-utils

Add OID related methods to FFI

95835 of 104725 relevant lines covered (91.51%)

13037929.75 hits per line

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

92.91
/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_oid.h>
16
#include <botan/internal/ffi_pkey.h>
17
#include <botan/internal/ffi_rng.h>
18
#include <botan/internal/ffi_util.h>
19

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

24
extern "C" {
25

26
using namespace Botan_FFI;
27

28
int botan_privkey_create(botan_privkey_t* key_obj,
85✔
29
                         const char* algo_name,
30
                         const char* algo_params,
31
                         botan_rng_t rng_obj) {
32
   return ffi_guard_thunk(__func__, [=]() -> int {
85✔
33
      if(key_obj == nullptr) {
85✔
34
         return BOTAN_FFI_ERROR_NULL_POINTER;
35
      }
36

37
      *key_obj = nullptr;
85✔
38
      if(rng_obj == nullptr) {
85✔
39
         return BOTAN_FFI_ERROR_NULL_POINTER;
40
      }
41

42
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
85✔
43
      std::unique_ptr<Botan::Private_Key> key(
85✔
44
         Botan::create_private_key(algo_name ? algo_name : "RSA", rng, algo_params ? algo_params : ""));
255✔
45

46
      if(key) {
85✔
47
         *key_obj = new botan_privkey_struct(std::move(key));
85✔
48
         return BOTAN_FFI_SUCCESS;
85✔
49
      } else {
50
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
51
      }
52
   });
85✔
53
}
54

55
int botan_privkey_load(
51✔
56
   botan_privkey_t* key, botan_rng_t rng_obj, const uint8_t bits[], size_t len, const char* password) {
57
   BOTAN_UNUSED(rng_obj);
51✔
58

59
   *key = nullptr;
51✔
60

61
   return ffi_guard_thunk(__func__, [=]() -> int {
51✔
62
      Botan::DataSource_Memory src(bits, len);
51✔
63

64
      std::unique_ptr<Botan::Private_Key> pkcs8;
51✔
65

66
      if(password == nullptr) {
51✔
67
         pkcs8 = Botan::PKCS8::load_key(src);
22✔
68
      } else {
69
         pkcs8 = Botan::PKCS8::load_key(src, std::string(password));
29✔
70
      }
71

72
      if(pkcs8) {
51✔
73
         *key = new botan_privkey_struct(std::move(pkcs8));
51✔
74
         return BOTAN_FFI_SUCCESS;
51✔
75
      }
76
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
77
   });
102✔
78
}
79

80
int botan_privkey_destroy(botan_privkey_t key) {
214✔
81
   return BOTAN_FFI_CHECKED_DELETE(key);
214✔
82
}
83

84
int botan_pubkey_load(botan_pubkey_t* key, const uint8_t bits[], size_t bits_len) {
12✔
85
   *key = nullptr;
12✔
86

87
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
88
      Botan::DataSource_Memory src(bits, bits_len);
12✔
89
      std::unique_ptr<Botan::Public_Key> pubkey(Botan::X509::load_key(src));
12✔
90

91
      if(pubkey == nullptr) {
12✔
92
         return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
93
      }
94

95
      *key = new botan_pubkey_struct(std::move(pubkey));
12✔
96
      return BOTAN_FFI_SUCCESS;
12✔
97
   });
24✔
98
}
99

100
int botan_pubkey_destroy(botan_pubkey_t key) {
179✔
101
   return BOTAN_FFI_CHECKED_DELETE(key);
179✔
102
}
103

104
int botan_privkey_export_pubkey(botan_pubkey_t* pubout, botan_privkey_t key_obj) {
91✔
105
   return ffi_guard_thunk(__func__, [=]() -> int {
91✔
106
      auto public_key = safe_get(key_obj).public_key();
91✔
107
      *pubout = new botan_pubkey_struct(std::move(public_key));
91✔
108
      return BOTAN_FFI_SUCCESS;
91✔
109
   });
91✔
110
}
111

112
int botan_privkey_algo_name(botan_privkey_t key, char out[], size_t* out_len) {
2✔
113
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { return write_str_output(out, out_len, k.algo_name()); });
4✔
114
}
115

116
int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len) {
7✔
117
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { return write_str_output(out, out_len, k.algo_name()); });
14✔
118
}
119

120
int botan_pubkey_check_key(botan_pubkey_t key, botan_rng_t rng, uint32_t flags) {
25✔
121
   const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS);
25✔
122

123
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
50✔
124
      return (k.check_key(safe_get(rng), strong) == true) ? 0 : BOTAN_FFI_ERROR_INVALID_INPUT;
125
   });
126
}
127

128
int botan_privkey_check_key(botan_privkey_t key, botan_rng_t rng, uint32_t flags) {
16✔
129
   const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS);
16✔
130
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
32✔
131
      return (k.check_key(safe_get(rng), strong) == true) ? 0 : BOTAN_FFI_ERROR_INVALID_INPUT;
132
   });
133
}
134

135
int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags) {
44✔
136
   if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
44✔
137
      return copy_view_bin(out, out_len, botan_pubkey_view_der, key);
22✔
138
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
22✔
139
      return copy_view_str(out, out_len, botan_pubkey_view_pem, key);
22✔
140
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_RAW) {
×
141
      return copy_view_bin(out, out_len, botan_pubkey_view_raw, key);
×
142
   } else {
143
      return BOTAN_FFI_ERROR_BAD_FLAG;
144
   }
145
}
146

147
int botan_pubkey_view_der(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
23✔
148
   return BOTAN_FFI_VISIT(
92✔
149
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, k.subject_public_key()); });
150
}
151

152
int botan_pubkey_view_pem(botan_pubkey_t key, botan_view_ctx ctx, botan_view_str_fn view) {
26✔
153
   return BOTAN_FFI_VISIT(
78✔
154
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, Botan::X509::PEM_encode(k)); });
155
}
156

157
int botan_pubkey_view_raw(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
110✔
158
   return BOTAN_FFI_VISIT(
438✔
159
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, k.raw_public_key_bits()); });
160
}
161

162
int botan_privkey_export(botan_privkey_t key, uint8_t out[], size_t* out_len, uint32_t flags) {
44✔
163
   if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
44✔
164
      return copy_view_bin(out, out_len, botan_privkey_view_der, key);
22✔
165
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
22✔
166
      return copy_view_str(out, out_len, botan_privkey_view_pem, key);
22✔
167
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_RAW) {
×
168
      return copy_view_bin(out, out_len, botan_privkey_view_raw, key);
×
169
   } else {
170
      return BOTAN_FFI_ERROR_BAD_FLAG;
171
   }
172
}
173

174
int botan_privkey_view_der(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
27✔
175
   return BOTAN_FFI_VISIT(
108✔
176
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, Botan::PKCS8::BER_encode(k)); });
177
}
178

179
int botan_privkey_view_pem(botan_privkey_t key, botan_view_ctx ctx, botan_view_str_fn view) {
34✔
180
   return BOTAN_FFI_VISIT(
102✔
181
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, Botan::PKCS8::PEM_encode(k)); });
182
}
183

184
int botan_privkey_view_raw(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
110✔
185
   return BOTAN_FFI_VISIT(
438✔
186
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, k.raw_private_key_bits()); });
187
}
188

189
int botan_privkey_export_encrypted(botan_privkey_t key,
×
190
                                   uint8_t out[],
191
                                   size_t* out_len,
192
                                   botan_rng_t rng_obj,
193
                                   const char* pass,
194
                                   const char* /*ignored - pbe*/,
195
                                   uint32_t flags) {
196
   return botan_privkey_export_encrypted_pbkdf_iter(key, out, out_len, rng_obj, pass, 100000, nullptr, nullptr, flags);
×
197
}
198

199
int botan_privkey_export_encrypted_pbkdf_msec(botan_privkey_t key,
11✔
200
                                              uint8_t out[],
201
                                              size_t* out_len,
202
                                              botan_rng_t rng,
203
                                              const char* passphrase,
204
                                              uint32_t pbkdf_msec,
205
                                              size_t* pbkdf_iters_out,
206
                                              const char* cipher,
207
                                              const char* pbkdf_hash,
208
                                              uint32_t flags) {
209
   if(pbkdf_iters_out) {
11✔
210
      *pbkdf_iters_out = 0;
11✔
211
   }
212

213
   if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
11✔
214
      return copy_view_bin(
11✔
215
         out, out_len, botan_privkey_view_encrypted_der_timed, key, rng, passphrase, cipher, pbkdf_hash, pbkdf_msec);
11✔
216
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
×
217
      return copy_view_str(
×
218
         out, out_len, botan_privkey_view_encrypted_pem_timed, key, rng, passphrase, cipher, pbkdf_hash, pbkdf_msec);
×
219
   } else {
220
      return BOTAN_FFI_ERROR_BAD_FLAG;
221
   }
222
}
223

224
int botan_privkey_view_encrypted_der_timed(botan_privkey_t key,
14✔
225
                                           botan_rng_t rng_obj,
226
                                           const char* passphrase,
227
                                           const char* maybe_cipher,
228
                                           const char* maybe_pbkdf_algo,
229
                                           size_t pbkdf_runtime_msec,
230
                                           botan_view_ctx ctx,
231
                                           botan_view_bin_fn view) {
232
   if(passphrase == nullptr) {
14✔
233
      return BOTAN_FFI_ERROR_NULL_POINTER;
234
   }
235

236
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
95✔
237
      const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
238
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
239

240
      const std::string cipher = (maybe_cipher ? maybe_cipher : "");
241
      const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
242

243
      auto pkcs8 =
244
         Botan::PKCS8::BER_encode_encrypted_pbkdf_msec(k, rng, passphrase, pbkdf_time, nullptr, cipher, pbkdf_algo);
245

246
      return invoke_view_callback(view, ctx, pkcs8);
247
   });
248
}
249

250
int botan_privkey_view_encrypted_pem_timed(botan_privkey_t key,
3✔
251
                                           botan_rng_t rng_obj,
252
                                           const char* passphrase,
253
                                           const char* maybe_cipher,
254
                                           const char* maybe_pbkdf_algo,
255
                                           size_t pbkdf_runtime_msec,
256
                                           botan_view_ctx ctx,
257
                                           botan_view_str_fn view) {
258
   if(passphrase == nullptr) {
3✔
259
      return BOTAN_FFI_ERROR_NULL_POINTER;
260
   }
261

262
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
15✔
263
      const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
264
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
265

266
      const std::string cipher = (maybe_cipher ? maybe_cipher : "");
267
      const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
268

269
      auto pkcs8 =
270
         Botan::PKCS8::PEM_encode_encrypted_pbkdf_msec(k, rng, passphrase, pbkdf_time, nullptr, cipher, pbkdf_algo);
271

272
      return invoke_view_callback(view, ctx, pkcs8);
273
   });
274
}
275

276
int botan_privkey_export_encrypted_pbkdf_iter(botan_privkey_t key,
44✔
277
                                              uint8_t out[],
278
                                              size_t* out_len,
279
                                              botan_rng_t rng,
280
                                              const char* passphrase,
281
                                              size_t pbkdf_iter,
282
                                              const char* cipher,
283
                                              const char* pbkdf_algo,
284
                                              uint32_t flags) {
285
   if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
44✔
286
      return copy_view_bin(
22✔
287
         out, out_len, botan_privkey_view_encrypted_der, key, rng, passphrase, cipher, pbkdf_algo, pbkdf_iter);
22✔
288
   } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
22✔
289
      return copy_view_str(
22✔
290
         out, out_len, botan_privkey_view_encrypted_pem, key, rng, passphrase, cipher, pbkdf_algo, pbkdf_iter);
22✔
291
   } else {
292
      return BOTAN_FFI_ERROR_BAD_FLAG;
293
   }
294
}
295

296
int botan_privkey_view_encrypted_der(botan_privkey_t key,
22✔
297
                                     botan_rng_t rng_obj,
298
                                     const char* passphrase,
299
                                     const char* maybe_cipher,
300
                                     const char* maybe_pbkdf_algo,
301
                                     size_t maybe_pbkdf_iterations,
302
                                     botan_view_ctx ctx,
303
                                     botan_view_bin_fn view) {
304
   if(passphrase == nullptr) {
22✔
305
      return BOTAN_FFI_ERROR_NULL_POINTER;
306
   }
307

308
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
176✔
309
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
310

311
      const std::string cipher = (maybe_cipher ? maybe_cipher : "");
312
      const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
313
      const size_t pbkdf_iter = (maybe_pbkdf_iterations ? maybe_pbkdf_iterations : 100000);
314

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

317
      return invoke_view_callback(view, ctx, pkcs8);
318
   });
319
}
320

321
int botan_privkey_view_encrypted_pem(botan_privkey_t key,
22✔
322
                                     botan_rng_t rng_obj,
323
                                     const char* passphrase,
324
                                     const char* maybe_cipher,
325
                                     const char* maybe_pbkdf_algo,
326
                                     size_t maybe_pbkdf_iterations,
327
                                     botan_view_ctx ctx,
328
                                     botan_view_str_fn view) {
329
   if(passphrase == nullptr) {
22✔
330
      return BOTAN_FFI_ERROR_NULL_POINTER;
331
   }
332

333
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
154✔
334
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
335

336
      const std::string cipher = (maybe_cipher ? maybe_cipher : "");
337
      const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
338
      const size_t pbkdf_iter = (maybe_pbkdf_iterations ? maybe_pbkdf_iterations : 100000);
339

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

342
      return invoke_view_callback(view, ctx, pkcs8);
343
   });
344
}
345

346
int botan_pubkey_oid(botan_asn1_oid_t* oid, botan_pubkey_t key) {
2✔
347
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
348
      if(oid == nullptr) {
349
         return BOTAN_FFI_ERROR_NULL_POINTER;
350
      }
351

352
      std::unique_ptr<Botan::OID> o = std::make_unique<Botan::OID>(k.object_identifier());
353
      *oid = new botan_asn1_oid_struct(std::move(o));
354

355
      return BOTAN_FFI_SUCCESS;
356
   });
357
}
358

359
int botan_privkey_oid(botan_asn1_oid_t* oid, botan_privkey_t key) {
2✔
360
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
361
      if(oid == nullptr) {
362
         return BOTAN_FFI_ERROR_NULL_POINTER;
363
      }
364

365
      std::unique_ptr<Botan::OID> o = std::make_unique<Botan::OID>(k.object_identifier());
366
      *oid = new botan_asn1_oid_struct(std::move(o));
367

368
      return BOTAN_FFI_SUCCESS;
369
   });
370
}
371

372
int botan_privkey_stateful_operation(botan_privkey_t key, int* out) {
5✔
373
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
10✔
374
      if(out == nullptr) {
375
         return BOTAN_FFI_ERROR_NULL_POINTER;
376
      }
377

378
      if(k.stateful_operation()) {
379
         *out = 1;
380
      } else {
381
         *out = 0;
382
      }
383
      return BOTAN_FFI_SUCCESS;
384
   });
385
}
386

387
int botan_privkey_remaining_operations(botan_privkey_t key, uint64_t* out) {
5✔
388
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
10✔
389
      if(out == nullptr) {
390
         return BOTAN_FFI_ERROR_NULL_POINTER;
391
      }
392

393
      if(auto remaining = k.remaining_operations()) {
394
         *out = remaining.value();
395
         return BOTAN_FFI_SUCCESS;
396
      } else {
397
         return BOTAN_FFI_ERROR_NO_VALUE;
398
      }
399
   });
400
}
401

402
int botan_pubkey_estimated_strength(botan_pubkey_t key, size_t* estimate) {
14✔
403
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { *estimate = k.estimated_strength(); });
28✔
404
}
405

406
int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash_fn, uint8_t out[], size_t* out_len) {
22✔
407
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
110✔
408
      auto h = Botan::HashFunction::create_or_throw(hash_fn);
409
      return write_vec_output(out, out_len, h->process(k.public_key_bits()));
410
   });
411
}
412

413
int botan_pkcs_hash_id(const char* hash_name, uint8_t pkcs_id[], size_t* pkcs_id_len) {
2✔
414
#if defined(BOTAN_HAS_HASH_ID)
415
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
416
      const std::vector<uint8_t> hash_id = Botan::pkcs_hash_id(hash_name);
2✔
417
      return write_output(pkcs_id, pkcs_id_len, hash_id.data(), hash_id.size());
2✔
418
   });
2✔
419
#else
420
   BOTAN_UNUSED(hash_name, pkcs_id, pkcs_id_len);
421
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
422
#endif
423
}
424
}
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