Botan 3.0.0
Crypto and TLS for C&
ffi_pkey.cpp
Go to the documentation of this file.
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#include <botan/internal/ffi_util.h>
9#include <botan/internal/ffi_pkey.h>
10#include <botan/internal/ffi_rng.h>
11#include <botan/data_src.h>
12#include <botan/hash.h>
13#include <botan/pkcs8.h>
14#include <botan/pk_keys.h>
15#include <botan/x509_key.h>
16#include <botan/pk_algs.h>
17
18#if defined(BOTAN_HAS_HASH_ID)
19 #include <botan/internal/hash_id.h>
20#endif
21
22extern "C" {
23
24using namespace Botan_FFI;
25
27 const char* algo_name,
28 const char* algo_params,
29 botan_rng_t rng_obj)
30 {
31 return ffi_guard_thunk(__func__, [=]() -> int {
32 if(key_obj == nullptr)
34
35 *key_obj = nullptr;
36 if(rng_obj == nullptr)
38
40 std::unique_ptr<Botan::Private_Key> key(
41 Botan::create_private_key(algo_name ? algo_name : "RSA",
42 rng,
43 algo_params ? algo_params : ""));
44
45 if(key)
46 {
47 *key_obj = new botan_privkey_struct(std::move(key));
48 return BOTAN_FFI_SUCCESS;
49 }
50 else
51 {
53 }
54 });
55 }
56
58 const uint8_t bits[], size_t len,
59 const char* password)
60 {
61 BOTAN_UNUSED(rng_obj);
62
63 *key = nullptr;
64
65 return ffi_guard_thunk(__func__, [=]() -> int {
66 Botan::DataSource_Memory src(bits, len);
67
68 std::unique_ptr<Botan::Private_Key> pkcs8;
69
70 if(password == nullptr)
71 {
72 pkcs8 = Botan::PKCS8::load_key(src);
73 }
74 else
75 {
76 pkcs8 = Botan::PKCS8::load_key(src, std::string(password));
77 }
78
79 if(pkcs8)
80 {
81 *key = new botan_privkey_struct(std::move(pkcs8));
82 return BOTAN_FFI_SUCCESS;
83 }
85 });
86 }
87
89 {
90 return BOTAN_FFI_CHECKED_DELETE(key);
91 }
92
94 const uint8_t bits[], size_t bits_len)
95 {
96 *key = nullptr;
97
98 return ffi_guard_thunk(__func__, [=]() -> int {
99 Botan::DataSource_Memory src(bits, bits_len);
100 std::unique_ptr<Botan::Public_Key> pubkey(Botan::X509::load_key(src));
101
102 if(pubkey == nullptr)
104
105 *key = new botan_pubkey_struct(std::move(pubkey));
106 return BOTAN_FFI_SUCCESS;
107 });
108 }
109
111 {
112 return BOTAN_FFI_CHECKED_DELETE(key);
113 }
114
116 {
117 return ffi_guard_thunk(__func__, [=]() -> int {
118 auto public_key = safe_get(key_obj).public_key();
119 *pubout = new botan_pubkey_struct(std::move(public_key));
120 return BOTAN_FFI_SUCCESS;
121 });
122 }
123
124int botan_privkey_algo_name(botan_privkey_t key, char out[], size_t* out_len)
125 {
126 return BOTAN_FFI_VISIT(key, [=](const auto& k) { return write_str_output(out, out_len, k.algo_name()); });
127 }
128
129int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len)
130 {
131 return BOTAN_FFI_VISIT(key, [=](const auto& k) { return write_str_output(out, out_len, k.algo_name()); });
132 }
133
135 {
136 const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS);
137
138 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
139 return (k.check_key(safe_get(rng), strong) == true) ? 0 : BOTAN_FFI_ERROR_INVALID_INPUT;
140 });
141 }
142
144 {
145 const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS);
146 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
147 return (k.check_key(safe_get(rng), strong) == true) ? 0 : BOTAN_FFI_ERROR_INVALID_INPUT;
148 });
149 }
150
151int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
152 {
154 return copy_view_bin(out, out_len, botan_pubkey_view_der, key);
155 else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
156 return copy_view_str(out, out_len, botan_pubkey_view_pem, key);
157 else
159 }
160
162 {
163 return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int
164 {
165 return invoke_view_callback(view, ctx, Botan::X509::BER_encode(k));
166 });
167 }
168
170 {
171 return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int
172 {
173 return invoke_view_callback(view, ctx, Botan::X509::PEM_encode(k));
174 });
175 }
176
177int botan_privkey_export(botan_privkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
178 {
180 return copy_view_bin(out, out_len, botan_privkey_view_der, key);
181 else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
182 return copy_view_str(out, out_len, botan_privkey_view_pem, key);
183 else
185 }
186
188 {
189 return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int
190 {
192 });
193 }
194
196 {
197 return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int
198 {
200 });
201 }
202
204 uint8_t out[], size_t* out_len,
205 botan_rng_t rng_obj,
206 const char* pass,
207 const char* /*ignored - pbe*/,
208 uint32_t flags)
209 {
210 return botan_privkey_export_encrypted_pbkdf_iter(key, out, out_len, rng_obj, pass, 100000, nullptr, nullptr, flags);
211 }
212
214 uint8_t out[], size_t* out_len,
215 botan_rng_t rng,
216 const char* passphrase,
217 uint32_t pbkdf_msec,
218 size_t* pbkdf_iters_out,
219 const char* cipher,
220 const char* pbkdf_hash,
221 uint32_t flags)
222 {
223 if(pbkdf_iters_out)
224 *pbkdf_iters_out = 0;
225
227 {
229 key, rng, passphrase, cipher, pbkdf_hash, pbkdf_msec);
230 }
231 else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
232 {
234 key, rng, passphrase, cipher, pbkdf_hash, pbkdf_msec);
235 }
236 else
237 {
239 }
240 }
241
243 botan_privkey_t key,
244 botan_rng_t rng_obj,
245 const char* passphrase,
246 const char* maybe_cipher,
247 const char* maybe_pbkdf_algo,
248 size_t pbkdf_runtime_msec,
249 botan_view_ctx ctx,
251 {
252 if(passphrase == nullptr)
254
255 return BOTAN_FFI_VISIT(key, [=](const auto& k)
256 {
257 const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
259
260 const std::string cipher = (maybe_cipher ? maybe_cipher : "");
261 const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
262
264 k, rng, passphrase, pbkdf_time, nullptr, cipher, pbkdf_algo);
265
266 return invoke_view_callback(view, ctx, pkcs8);
267 });
268 }
269
271 botan_privkey_t key,
272 botan_rng_t rng_obj,
273 const char* passphrase,
274 const char* maybe_cipher,
275 const char* maybe_pbkdf_algo,
276 size_t pbkdf_runtime_msec,
277 botan_view_ctx ctx,
279 {
280 if(passphrase == nullptr)
282
283 return BOTAN_FFI_VISIT(key, [=](const auto& k)
284 {
285 const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
287
288 const std::string cipher = (maybe_cipher ? maybe_cipher : "");
289 const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
290
292 k, rng, passphrase, pbkdf_time, nullptr, cipher, pbkdf_algo);
293
294 return invoke_view_callback(view, ctx, pkcs8);
295 });
296 }
297
299 uint8_t out[], size_t* out_len,
300 botan_rng_t rng,
301 const char* passphrase,
302 size_t pbkdf_iter,
303 const char* cipher,
304 const char* pbkdf_algo,
305 uint32_t flags)
306 {
308 {
310 key, rng, passphrase, cipher, pbkdf_algo, pbkdf_iter);
311 }
312 else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
313 {
315 key, rng, passphrase, cipher, pbkdf_algo, pbkdf_iter);
316 }
317 else
318 {
320 }
321 }
322
324 botan_privkey_t key,
325 botan_rng_t rng_obj,
326 const char* passphrase,
327 const char* maybe_cipher,
328 const char* maybe_pbkdf_algo,
329 size_t maybe_pbkdf_iterations,
330 botan_view_ctx ctx,
332 {
333 if(passphrase == nullptr)
335
336 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
338
339 const std::string cipher = (maybe_cipher ? maybe_cipher : "");
340 const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
341 const size_t pbkdf_iter = (maybe_pbkdf_iterations ? maybe_pbkdf_iterations : 100000);
342
343 auto pkcs8 = Botan::PKCS8::BER_encode_encrypted_pbkdf_iter(k, rng, passphrase, pbkdf_iter, cipher, pbkdf_algo);
344
345 return invoke_view_callback(view, ctx, pkcs8);
346 });
347 }
348
350 botan_privkey_t key,
351 botan_rng_t rng_obj,
352 const char* passphrase,
353 const char* maybe_cipher,
354 const char* maybe_pbkdf_algo,
355 size_t maybe_pbkdf_iterations,
356 botan_view_ctx ctx,
358 {
359 if(passphrase == nullptr)
361
362 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
364
365 const std::string cipher = (maybe_cipher ? maybe_cipher : "");
366 const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
367 const size_t pbkdf_iter = (maybe_pbkdf_iterations ? maybe_pbkdf_iterations : 100000);
368
369 auto pkcs8 = Botan::PKCS8::PEM_encode_encrypted_pbkdf_iter(k, rng, passphrase, pbkdf_iter, cipher, pbkdf_algo);
370
371 return invoke_view_callback(view, ctx, pkcs8);
372 });
373 }
374
376 {
377 return BOTAN_FFI_VISIT(key, [=](const auto& k) { *estimate = k.estimated_strength(); });
378 }
379
380int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash_fn,
381 uint8_t out[], size_t* out_len)
382 {
383 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
384 auto h = Botan::HashFunction::create_or_throw(hash_fn);
385 return write_vec_output(out, out_len, h->process(k.public_key_bits()));
386 });
387 }
388
389int botan_pkcs_hash_id(const char* hash_name, uint8_t pkcs_id[], size_t* pkcs_id_len)
390 {
391#if defined(BOTAN_HAS_HASH_ID)
392 return ffi_guard_thunk(__func__, [=]() -> int {
393 const std::vector<uint8_t> hash_id = Botan::pkcs_hash_id(hash_name);
394 return write_output(pkcs_id, pkcs_id_len, hash_id.data(), hash_id.size());
395 });
396#else
397 BOTAN_UNUSED(hash_name, pkcs_id, pkcs_id_len);
399#endif
400 }
401
402}
#define BOTAN_UNUSED(...)
Definition: assert.h:141
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition: hash.cpp:320
struct botan_pubkey_struct * botan_pubkey_t
Definition: ffi.h:1255
struct botan_privkey_struct * botan_privkey_t
Definition: ffi.h:1028
int(* botan_view_bin_fn)(botan_view_ctx view_ctx, const uint8_t *data, size_t len)
Definition: ffi.h:110
#define BOTAN_PRIVKEY_EXPORT_FLAG_PEM
Definition: ffi.h:1123
#define BOTAN_CHECK_KEY_EXPENSIVE_TESTS
Definition: ffi.h:1043
void * botan_view_ctx
Definition: ffi.h:101
struct botan_rng_struct * botan_rng_t
Definition: ffi.h:229
#define BOTAN_PRIVKEY_EXPORT_FLAG_DER
Definition: ffi.h:1122
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition: ffi.h:91
@ BOTAN_FFI_ERROR_UNKNOWN_ERROR
Definition: ffi.h:98
@ BOTAN_FFI_ERROR_BAD_FLAG
Definition: ffi.h:84
@ BOTAN_FFI_ERROR_INVALID_INPUT
Definition: ffi.h:73
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition: ffi.h:85
@ BOTAN_FFI_SUCCESS
Definition: ffi.h:70
int(* botan_view_str_fn)(botan_view_ctx view_ctx, const char *str, size_t len)
Definition: ffi.h:119
int botan_privkey_export_encrypted(botan_privkey_t key, uint8_t out[], size_t *out_len, botan_rng_t rng_obj, const char *pass, const char *, uint32_t flags)
Definition: ffi_pkey.cpp:203
int botan_privkey_check_key(botan_privkey_t key, botan_rng_t rng, uint32_t flags)
Definition: ffi_pkey.cpp:143
int botan_pubkey_fingerprint(botan_pubkey_t key, const char *hash_fn, uint8_t out[], size_t *out_len)
Definition: ffi_pkey.cpp:380
int botan_privkey_load(botan_privkey_t *key, botan_rng_t rng_obj, const uint8_t bits[], size_t len, const char *password)
Definition: ffi_pkey.cpp:57
int botan_pubkey_estimated_strength(botan_pubkey_t key, size_t *estimate)
Definition: ffi_pkey.cpp:375
int botan_pkcs_hash_id(const char *hash_name, uint8_t pkcs_id[], size_t *pkcs_id_len)
Definition: ffi_pkey.cpp:389
int botan_privkey_view_encrypted_der_timed(botan_privkey_t key, botan_rng_t rng_obj, const char *passphrase, const char *maybe_cipher, const char *maybe_pbkdf_algo, size_t pbkdf_runtime_msec, botan_view_ctx ctx, botan_view_bin_fn view)
Definition: ffi_pkey.cpp:242
int botan_pubkey_load(botan_pubkey_t *key, const uint8_t bits[], size_t bits_len)
Definition: ffi_pkey.cpp:93
int botan_privkey_export(botan_privkey_t key, uint8_t out[], size_t *out_len, uint32_t flags)
Definition: ffi_pkey.cpp:177
int botan_privkey_view_encrypted_pem_timed(botan_privkey_t key, botan_rng_t rng_obj, const char *passphrase, const char *maybe_cipher, const char *maybe_pbkdf_algo, size_t pbkdf_runtime_msec, botan_view_ctx ctx, botan_view_str_fn view)
Definition: ffi_pkey.cpp:270
int botan_privkey_export_encrypted_pbkdf_msec(botan_privkey_t key, uint8_t out[], size_t *out_len, botan_rng_t rng, const char *passphrase, uint32_t pbkdf_msec, size_t *pbkdf_iters_out, const char *cipher, const char *pbkdf_hash, uint32_t flags)
Definition: ffi_pkey.cpp:213
int botan_privkey_view_encrypted_der(botan_privkey_t key, botan_rng_t rng_obj, const char *passphrase, const char *maybe_cipher, const char *maybe_pbkdf_algo, size_t maybe_pbkdf_iterations, botan_view_ctx ctx, botan_view_bin_fn view)
Definition: ffi_pkey.cpp:323
int botan_privkey_destroy(botan_privkey_t key)
Definition: ffi_pkey.cpp:88
int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t *out_len)
Definition: ffi_pkey.cpp:129
int botan_pubkey_view_pem(botan_pubkey_t key, botan_view_ctx ctx, botan_view_str_fn view)
Definition: ffi_pkey.cpp:169
int botan_privkey_view_der(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view)
Definition: ffi_pkey.cpp:187
int botan_pubkey_view_der(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view)
Definition: ffi_pkey.cpp:161
int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t *out_len, uint32_t flags)
Definition: ffi_pkey.cpp:151
int botan_pubkey_destroy(botan_pubkey_t key)
Definition: ffi_pkey.cpp:110
int botan_privkey_algo_name(botan_privkey_t key, char out[], size_t *out_len)
Definition: ffi_pkey.cpp:124
int botan_privkey_create(botan_privkey_t *key_obj, const char *algo_name, const char *algo_params, botan_rng_t rng_obj)
Definition: ffi_pkey.cpp:26
int botan_privkey_export_pubkey(botan_pubkey_t *pubout, botan_privkey_t key_obj)
Definition: ffi_pkey.cpp:115
int botan_pubkey_check_key(botan_pubkey_t key, botan_rng_t rng, uint32_t flags)
Definition: ffi_pkey.cpp:134
int botan_privkey_export_encrypted_pbkdf_iter(botan_privkey_t key, uint8_t out[], size_t *out_len, botan_rng_t rng, const char *passphrase, size_t pbkdf_iter, const char *cipher, const char *pbkdf_algo, uint32_t flags)
Definition: ffi_pkey.cpp:298
int botan_privkey_view_pem(botan_privkey_t key, botan_view_ctx ctx, botan_view_str_fn view)
Definition: ffi_pkey.cpp:195
int botan_privkey_view_encrypted_pem(botan_privkey_t key, botan_rng_t rng_obj, const char *passphrase, const char *maybe_cipher, const char *maybe_pbkdf_algo, size_t maybe_pbkdf_iterations, botan_view_ctx ctx, botan_view_str_fn view)
Definition: ffi_pkey.cpp:349
#define BOTAN_FFI_VISIT(obj, lambda)
Definition: ffi_util.h:126
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition: ffi_util.h:145
std::vector< uint8_t > BER_encode(const Private_Key &key, RandomNumberGenerator &rng, std::string_view pass, std::chrono::milliseconds msec, std::string_view pbe_algo)
Definition: pkcs8.cpp:194
std::string PEM_encode_encrypted_pbkdf_iter(const Private_Key &key, RandomNumberGenerator &rng, std::string_view pass, size_t pbkdf_iterations, std::string_view cipher, std::string_view pbkdf_hash)
Definition: pkcs8.cpp:273
std::string PEM_encode(const Private_Key &key)
Definition: pkcs8.cpp:142
std::string PEM_encode_encrypted_pbkdf_msec(const Private_Key &key, RandomNumberGenerator &rng, std::string_view pass, std::chrono::milliseconds pbkdf_msec, size_t *pbkdf_iterations, std::string_view cipher, std::string_view pbkdf_hash)
Definition: pkcs8.cpp:321
std::vector< uint8_t > BER_encode_encrypted_pbkdf_iter(const Private_Key &key, RandomNumberGenerator &rng, std::string_view pass, size_t pbkdf_iterations, std::string_view cipher, std::string_view pbkdf_hash)
Definition: pkcs8.cpp:240
std::vector< uint8_t > BER_encode_encrypted_pbkdf_msec(const Private_Key &key, RandomNumberGenerator &rng, std::string_view pass, std::chrono::milliseconds pbkdf_msec, size_t *pbkdf_iterations, std::string_view cipher, std::string_view pbkdf_hash)
Definition: pkcs8.cpp:288
std::unique_ptr< Private_Key > load_key(DataSource &source, const std::function< std::string()> &get_pass)
Definition: pkcs8.cpp:361
std::vector< uint8_t > BER_encode(const Public_Key &key)
Definition: x509_key.h:28
std::unique_ptr< Public_Key > load_key(DataSource &source)
Definition: x509_key.cpp:29
std::string PEM_encode(const Public_Key &key)
Definition: x509_key.cpp:20
int copy_view_bin(uint8_t out[], size_t *out_len, Fn fn, Args... args)
Definition: ffi_util.h:171
int write_str_output(uint8_t out[], size_t *out_len, std::string_view str)
Definition: ffi_util.h:219
T & safe_get(botan_struct< T, M > *p)
Definition: ffi_util.h:69
int invoke_view_callback(botan_view_bin_fn view, botan_view_ctx ctx, const std::vector< uint8_t, Alloc > &buf)
Definition: ffi_util.h:148
int copy_view_str(uint8_t out[], size_t *out_len, Fn fn, Args... args)
Definition: ffi_util.h:180
int ffi_guard_thunk(const char *func_name, const std::function< int()> &thunk)
Definition: ffi.cpp:120
int write_vec_output(uint8_t out[], size_t *out_len, const std::vector< uint8_t, Alloc > &buf)
Definition: ffi_util.h:214
int write_output(uint8_t out[], size_t *out_len, const uint8_t buf[], size_t buf_len)
Definition: ffi_util.h:190
std::unique_ptr< Private_Key > create_private_key(std::string_view alg_name, RandomNumberGenerator &rng, std::string_view params, std::string_view provider)
Definition: pk_algs.cpp:311
std::vector< uint8_t > pkcs_hash_id(std::string_view name)
Definition: hash_id.cpp:73