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

randombit / botan / 11303021523

12 Oct 2024 05:19AM UTC coverage: 91.118% (+0.005%) from 91.113%
11303021523

push

github

web-flow
Merge pull request #4368 from Rohde-Schwarz/ffi/raw_encode_asym_keys

90040 of 98817 relevant lines covered (91.12%)

9294050.32 hits per line

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

92.44
/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_pkey.h>
16
#include <botan/internal/ffi_rng.h>
17
#include <botan/internal/ffi_util.h>
18

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

23
extern "C" {
24

25
using namespace Botan_FFI;
26

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

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

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

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

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

58
   *key = nullptr;
51✔
59

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

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

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

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

79
int botan_privkey_destroy(botan_privkey_t key) {
107✔
80
   return BOTAN_FFI_CHECKED_DELETE(key);
107✔
81
}
82

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

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

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

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

99
int botan_pubkey_destroy(botan_pubkey_t key) {
74✔
100
   return BOTAN_FFI_CHECKED_DELETE(key);
74✔
101
}
102

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

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

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

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

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

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

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

146
int botan_pubkey_view_der(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
23✔
147
   return BOTAN_FFI_VISIT(
69✔
148
      key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, Botan::X509::BER_encode(k)); });
149
}
150

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

345
int botan_pubkey_estimated_strength(botan_pubkey_t key, size_t* estimate) {
14✔
346
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { *estimate = k.estimated_strength(); });
28✔
347
}
348

349
int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash_fn, uint8_t out[], size_t* out_len) {
22✔
350
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
110✔
351
      auto h = Botan::HashFunction::create_or_throw(hash_fn);
352
      return write_vec_output(out, out_len, h->process(k.public_key_bits()));
353
   });
354
}
355

356
int botan_pkcs_hash_id(const char* hash_name, uint8_t pkcs_id[], size_t* pkcs_id_len) {
2✔
357
#if defined(BOTAN_HAS_HASH_ID)
358
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
359
      const std::vector<uint8_t> hash_id = Botan::pkcs_hash_id(hash_name);
2✔
360
      return write_output(pkcs_id, pkcs_id_len, hash_id.data(), hash_id.size());
2✔
361
   });
4✔
362
#else
363
   BOTAN_UNUSED(hash_name, pkcs_id, pkcs_id_len);
364
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
365
#endif
366
}
367
}
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