Botan 3.6.1
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
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
23extern "C" {
24
25using namespace Botan_FFI;
26
28 const char* algo_name,
29 const char* algo_params,
30 botan_rng_t rng_obj) {
31 return ffi_guard_thunk(__func__, [=]() -> int {
32 if(key_obj == nullptr) {
34 }
35
36 *key_obj = nullptr;
37 if(rng_obj == nullptr) {
39 }
40
42 std::unique_ptr<Botan::Private_Key> key(
43 Botan::create_private_key(algo_name ? algo_name : "RSA", rng, algo_params ? algo_params : ""));
44
45 if(key) {
46 *key_obj = new botan_privkey_struct(std::move(key));
47 return BOTAN_FFI_SUCCESS;
48 } else {
50 }
51 });
52}
53
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);
57
58 *key = nullptr;
59
60 return ffi_guard_thunk(__func__, [=]() -> int {
61 Botan::DataSource_Memory src(bits, len);
62
63 std::unique_ptr<Botan::Private_Key> pkcs8;
64
65 if(password == nullptr) {
66 pkcs8 = Botan::PKCS8::load_key(src);
67 } else {
68 pkcs8 = Botan::PKCS8::load_key(src, std::string(password));
69 }
70
71 if(pkcs8) {
72 *key = new botan_privkey_struct(std::move(pkcs8));
73 return BOTAN_FFI_SUCCESS;
74 }
76 });
77}
78
82
83int botan_pubkey_load(botan_pubkey_t* key, const uint8_t bits[], size_t bits_len) {
84 *key = nullptr;
85
86 return ffi_guard_thunk(__func__, [=]() -> int {
87 Botan::DataSource_Memory src(bits, bits_len);
88 std::unique_ptr<Botan::Public_Key> pubkey(Botan::X509::load_key(src));
89
90 if(pubkey == nullptr) {
92 }
93
94 *key = new botan_pubkey_struct(std::move(pubkey));
95 return BOTAN_FFI_SUCCESS;
96 });
97}
98
102
104 return ffi_guard_thunk(__func__, [=]() -> int {
105 auto public_key = safe_get(key_obj).public_key();
106 *pubout = new botan_pubkey_struct(std::move(public_key));
107 return BOTAN_FFI_SUCCESS;
108 });
109}
110
111int botan_privkey_algo_name(botan_privkey_t key, char out[], size_t* out_len) {
112 return BOTAN_FFI_VISIT(key, [=](const auto& k) { return write_str_output(out, out_len, k.algo_name()); });
113}
114
115int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len) {
116 return BOTAN_FFI_VISIT(key, [=](const auto& k) { return write_str_output(out, out_len, k.algo_name()); });
117}
118
119int botan_pubkey_check_key(botan_pubkey_t key, botan_rng_t rng, uint32_t flags) {
120 const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS);
121
122 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
123 return (k.check_key(safe_get(rng), strong) == true) ? 0 : BOTAN_FFI_ERROR_INVALID_INPUT;
124 });
125}
126
128 const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS);
129 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
130 return (k.check_key(safe_get(rng), strong) == true) ? 0 : BOTAN_FFI_ERROR_INVALID_INPUT;
131 });
132}
133
134int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags) {
135 if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
136 return copy_view_bin(out, out_len, botan_pubkey_view_der, key);
137 } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
138 return copy_view_str(out, out_len, botan_pubkey_view_pem, key);
139 } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_RAW) {
140 return copy_view_bin(out, out_len, botan_pubkey_view_raw, key);
141 } else {
143 }
144}
145
147 return BOTAN_FFI_VISIT(
148 key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, Botan::X509::BER_encode(k)); });
149}
150
152 return BOTAN_FFI_VISIT(
153 key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, Botan::X509::PEM_encode(k)); });
154}
155
157 return BOTAN_FFI_VISIT(
158 key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, k.raw_public_key_bits()); });
159}
160
161int botan_privkey_export(botan_privkey_t key, uint8_t out[], size_t* out_len, uint32_t flags) {
162 if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
163 return copy_view_bin(out, out_len, botan_privkey_view_der, key);
164 } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
165 return copy_view_str(out, out_len, botan_privkey_view_pem, key);
166 } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_RAW) {
167 return copy_view_bin(out, out_len, botan_privkey_view_raw, key);
168 } else {
170 }
171}
172
174 return BOTAN_FFI_VISIT(
175 key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, Botan::PKCS8::BER_encode(k)); });
176}
177
179 return BOTAN_FFI_VISIT(
180 key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, Botan::PKCS8::PEM_encode(k)); });
181}
182
184 return BOTAN_FFI_VISIT(
185 key, [=](const auto& k) -> int { return invoke_view_callback(view, ctx, k.raw_private_key_bits()); });
186}
187
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
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) {
209 *pbkdf_iters_out = 0;
210 }
211
212 if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
213 return copy_view_bin(
214 out, out_len, botan_privkey_view_encrypted_der_timed, key, rng, passphrase, cipher, pbkdf_hash, pbkdf_msec);
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 {
220 }
221}
222
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) {
233 }
234
235 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
236 const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
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
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) {
259 }
260
261 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
262 const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
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
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) {
285 return copy_view_bin(
286 out, out_len, botan_privkey_view_encrypted_der, key, rng, passphrase, cipher, pbkdf_algo, pbkdf_iter);
287 } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
288 return copy_view_str(
289 out, out_len, botan_privkey_view_encrypted_pem, key, rng, passphrase, cipher, pbkdf_algo, pbkdf_iter);
290 } else {
292 }
293}
294
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) {
305 }
306
307 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
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
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) {
330 }
331
332 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
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
346 return BOTAN_FFI_VISIT(key, [=](const auto& k) { *estimate = k.estimated_strength(); });
347}
348
349int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash_fn, uint8_t out[], size_t* out_len) {
350 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
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
356int botan_pkcs_hash_id(const char* hash_name, uint8_t pkcs_id[], size_t* pkcs_id_len) {
357#if defined(BOTAN_HAS_HASH_ID)
358 return ffi_guard_thunk(__func__, [=]() -> int {
359 const std::vector<uint8_t> hash_id = Botan::pkcs_hash_id(hash_name);
360 return write_output(pkcs_id, pkcs_id_len, hash_id.data(), hash_id.size());
361 });
362#else
363 BOTAN_UNUSED(hash_name, pkcs_id, pkcs_id_len);
365#endif
366}
367}
#define BOTAN_UNUSED
Definition assert.h:118
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:298
struct botan_pubkey_struct * botan_pubkey_t
Definition ffi.h:1317
struct botan_privkey_struct * botan_privkey_t
Definition ffi.h:1097
#define BOTAN_PRIVKEY_EXPORT_FLAG_RAW
Definition ffi.h:1182
int(* botan_view_bin_fn)(botan_view_ctx view_ctx, const uint8_t *data, size_t len)
Definition ffi.h:155
#define BOTAN_PRIVKEY_EXPORT_FLAG_PEM
Definition ffi.h:1181
#define BOTAN_CHECK_KEY_EXPENSIVE_TESTS
Definition ffi.h:1110
void * botan_view_ctx
Definition ffi.h:146
struct botan_rng_struct * botan_rng_t
Definition ffi.h:272
#define BOTAN_PRIVKEY_EXPORT_FLAG_DER
Definition ffi.h:1180
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:135
@ BOTAN_FFI_ERROR_UNKNOWN_ERROR
Definition ffi.h:143
@ BOTAN_FFI_ERROR_BAD_FLAG
Definition ffi.h:128
@ BOTAN_FFI_ERROR_INVALID_INPUT
Definition ffi.h:117
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:129
@ BOTAN_FFI_SUCCESS
Definition ffi.h:114
int(* botan_view_str_fn)(botan_view_ctx view_ctx, const char *str, size_t len)
Definition ffi.h:164
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:188
int botan_privkey_check_key(botan_privkey_t key, botan_rng_t rng, uint32_t flags)
Definition ffi_pkey.cpp:127
int botan_pubkey_fingerprint(botan_pubkey_t key, const char *hash_fn, uint8_t out[], size_t *out_len)
Definition ffi_pkey.cpp:349
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:54
int botan_pubkey_estimated_strength(botan_pubkey_t key, size_t *estimate)
Definition ffi_pkey.cpp:345
int botan_pkcs_hash_id(const char *hash_name, uint8_t pkcs_id[], size_t *pkcs_id_len)
Definition ffi_pkey.cpp:356
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:223
int botan_pubkey_load(botan_pubkey_t *key, const uint8_t bits[], size_t bits_len)
Definition ffi_pkey.cpp:83
int botan_privkey_export(botan_privkey_t key, uint8_t out[], size_t *out_len, uint32_t flags)
Definition ffi_pkey.cpp:161
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:249
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:198
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:295
int botan_privkey_destroy(botan_privkey_t key)
Definition ffi_pkey.cpp:79
int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t *out_len)
Definition ffi_pkey.cpp:115
int botan_pubkey_view_pem(botan_pubkey_t key, botan_view_ctx ctx, botan_view_str_fn view)
Definition ffi_pkey.cpp:151
int botan_privkey_view_der(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view)
Definition ffi_pkey.cpp:173
int botan_privkey_view_raw(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view)
Definition ffi_pkey.cpp:183
int botan_pubkey_view_der(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view)
Definition ffi_pkey.cpp:146
int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t *out_len, uint32_t flags)
Definition ffi_pkey.cpp:134
int botan_pubkey_destroy(botan_pubkey_t key)
Definition ffi_pkey.cpp:99
int botan_privkey_algo_name(botan_privkey_t key, char out[], size_t *out_len)
Definition ffi_pkey.cpp:111
int botan_pubkey_view_raw(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view)
Definition ffi_pkey.cpp:156
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:27
int botan_privkey_export_pubkey(botan_pubkey_t *pubout, botan_privkey_t key_obj)
Definition ffi_pkey.cpp:103
int botan_pubkey_check_key(botan_pubkey_t key, botan_rng_t rng, uint32_t flags)
Definition ffi_pkey.cpp:119
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:275
int botan_privkey_view_pem(botan_privkey_t key, botan_view_ctx ctx, botan_view_str_fn view)
Definition ffi_pkey.cpp:178
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:320
#define BOTAN_FFI_VISIT(obj, lambda)
Definition ffi_util.h:124
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition ffi_util.h:143
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:163
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:233
std::string PEM_encode(const Private_Key &key)
Definition pkcs8.cpp:118
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:280
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:203
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:246
std::unique_ptr< Private_Key > load_key(DataSource &source, const std::function< std::string()> &get_pass)
Definition pkcs8.cpp:316
std::vector< uint8_t > BER_encode(const Public_Key &key)
Definition x509_key.h:23
std::unique_ptr< Public_Key > load_key(DataSource &source)
Definition x509_key.cpp:28
std::string PEM_encode(const Public_Key &key)
Definition x509_key.cpp:21
int copy_view_bin(uint8_t out[], size_t *out_len, Fn fn, Args... args)
Definition ffi_util.h:163
int write_str_output(uint8_t out[], size_t *out_len, std::string_view str)
Definition ffi_util.h:205
T & safe_get(botan_struct< T, M > *p)
Definition ffi_util.h:63
int invoke_view_callback(botan_view_bin_fn view, botan_view_ctx ctx, const std::vector< uint8_t, Alloc > &buf)
Definition ffi_util.h:146
int copy_view_str(uint8_t out[], size_t *out_len, Fn fn, Args... args)
Definition ffi_util.h:171
int ffi_guard_thunk(const char *func_name, const std::function< int()> &thunk)
Definition ffi.cpp:118
int write_vec_output(uint8_t out[], size_t *out_len, const std::vector< uint8_t, Alloc > &buf)
Definition ffi_util.h:201
int write_output(uint8_t out[], size_t *out_len, const uint8_t buf[], size_t buf_len)
Definition ffi_util.h:181
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:470
std::vector< uint8_t > pkcs_hash_id(std::string_view name)
Definition hash_id.cpp:78