Botan  2.11.0
Crypto and TLS for C++11
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/hash_id.h>
20 #endif
21 
22 extern "C" {
23 
24 using 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 
39  Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
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(key.release());
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(pkcs8.release());
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(pubkey.release());
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  std::unique_ptr<Botan::Public_Key>
120 
121  *pubout = new botan_pubkey_struct(pubkey.release());
122  return BOTAN_FFI_SUCCESS;
123  });
124  }
125 
126 int botan_privkey_algo_name(botan_privkey_t key, char out[], size_t* out_len)
127  {
128  return BOTAN_FFI_DO(Botan::Private_Key, key, k, { return write_str_output(out, out_len, k.algo_name()); });
129  }
130 
131 int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len)
132  {
133  return BOTAN_FFI_DO(Botan::Public_Key, key, k, { return write_str_output(out, out_len, k.algo_name()); });
134  }
135 
137  {
138  const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS);
139 
140  return BOTAN_FFI_DO(Botan::Public_Key, key, k,
141  { return (k.check_key(safe_get(rng), strong) == true) ? 0 : BOTAN_FFI_ERROR_INVALID_INPUT; });
142  }
143 
145  {
146  const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS);
147  return BOTAN_FFI_DO(Botan::Private_Key, key, k,
148  { return (k.check_key(safe_get(rng), strong) == true) ? 0 : BOTAN_FFI_ERROR_INVALID_INPUT; });
149  }
150 
151 int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
152  {
153  return BOTAN_FFI_DO(Botan::Public_Key, key, k, {
155  return write_vec_output(out, out_len, Botan::X509::BER_encode(k));
157  return write_str_output(out, out_len, Botan::X509::PEM_encode(k));
158  else
160  });
161  }
162 
163 int botan_privkey_export(botan_privkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
164  {
165  return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
167  return write_vec_output(out, out_len, Botan::PKCS8::BER_encode(k));
169  return write_str_output(out, out_len, Botan::PKCS8::PEM_encode(k));
170  else
172  });
173  }
174 
176  uint8_t out[], size_t* out_len,
177  botan_rng_t rng_obj,
178  const char* pass,
179  const char* /*ignored - pbe*/,
180  uint32_t flags)
181  {
182  return botan_privkey_export_encrypted_pbkdf_iter(key, out, out_len, rng_obj, pass, 100000, nullptr, nullptr, flags);
183  }
184 
186  uint8_t out[], size_t* out_len,
187  botan_rng_t rng_obj,
188  const char* pass,
189  uint32_t pbkdf_msec,
190  size_t* pbkdf_iters_out,
191  const char* maybe_cipher,
192  const char* maybe_pbkdf_hash,
193  uint32_t flags)
194  {
195  return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
196  const std::chrono::milliseconds pbkdf_time(pbkdf_msec);
197  Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
198 
199  const std::string cipher = (maybe_cipher ? maybe_cipher : "");
200  const std::string pbkdf_hash = (maybe_pbkdf_hash ? maybe_pbkdf_hash : "");
201 
203  {
204  return write_vec_output(out, out_len,
205  Botan::PKCS8::BER_encode_encrypted_pbkdf_msec(k, rng, pass, pbkdf_time, pbkdf_iters_out, cipher, pbkdf_hash));
206  }
208  {
209  return write_str_output(out, out_len,
210  Botan::PKCS8::PEM_encode_encrypted_pbkdf_msec(k, rng, pass, pbkdf_time, pbkdf_iters_out, cipher, pbkdf_hash));
211  }
212  else
213  {
214  return -2;
215  }
216  });
217  }
218 
220  uint8_t out[], size_t* out_len,
221  botan_rng_t rng_obj,
222  const char* pass,
223  size_t pbkdf_iter,
224  const char* maybe_cipher,
225  const char* maybe_pbkdf_hash,
226  uint32_t flags)
227  {
228  return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
229  Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
230 
231  const std::string cipher = (maybe_cipher ? maybe_cipher : "");
232  const std::string pbkdf_hash = (maybe_pbkdf_hash ? maybe_pbkdf_hash : "");
233 
235  {
236  return write_vec_output(out, out_len,
237  Botan::PKCS8::BER_encode_encrypted_pbkdf_iter(k, rng, pass, pbkdf_iter, cipher, pbkdf_hash));
238  }
240  {
241  return write_str_output(out, out_len,
242  Botan::PKCS8::PEM_encode_encrypted_pbkdf_iter(k, rng, pass, pbkdf_iter, cipher, pbkdf_hash));
243  }
244  else
245  {
246  return -2;
247  }
248  });
249  }
250 
252  {
253  return BOTAN_FFI_DO(Botan::Public_Key, key, k, { *estimate = k.estimated_strength(); });
254  }
255 
256 int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash_fn,
257  uint8_t out[], size_t* out_len)
258  {
259  return BOTAN_FFI_DO(Botan::Public_Key, key, k, {
260  std::unique_ptr<Botan::HashFunction> h(Botan::HashFunction::create(hash_fn));
261  return write_vec_output(out, out_len, h->process(k.public_key_bits()));
262  });
263  }
264 
265 int botan_pkcs_hash_id(const char* hash_name, uint8_t pkcs_id[], size_t* pkcs_id_len)
266  {
267 #if defined(BOTAN_HAS_HASH_ID)
268  return ffi_guard_thunk(__func__, [=]() -> int {
269  const std::vector<uint8_t> hash_id = Botan::pkcs_hash_id(hash_name);
270  return write_output(pkcs_id, pkcs_id_len, hash_id.data(), hash_id.size());
271  });
272 #else
274 #endif
275  }
276 
277 }
int ffi_guard_thunk(const char *func_name, std::function< int()> thunk)
Definition: ffi.cpp:86
int botan_privkey_destroy(botan_privkey_t key)
Definition: ffi_pkey.cpp:88
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
#define BOTAN_PRIVKEY_EXPORT_FLAG_PEM
Definition: ffi.h:1024
std::string PEM_encode(const Public_Key &key)
Definition: x509_key.cpp:28
int botan_privkey_export_pubkey(botan_pubkey_t *pubout, botan_privkey_t key_obj)
Definition: ffi_pkey.cpp:115
std::vector< uint8_t > BER_encode(const Public_Key &key)
Definition: x509_key.cpp:19
std::unique_ptr< Private_Key > create_private_key(const std::string &alg_name, RandomNumberGenerator &rng, const std::string &params, const std::string &provider)
Definition: pk_algs.cpp:268
Flags flags(Flag flags)
Definition: p11.h:858
int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t *out_len, uint32_t flags)
Definition: ffi_pkey.cpp:151
std::vector< uint8_t > BER_encode_encrypted_pbkdf_iter(const Private_Key &key, RandomNumberGenerator &rng, const std::string &pass, size_t pbkdf_iterations, const std::string &cipher, const std::string &pbkdf_hash)
Definition: pkcs8.cpp:246
int botan_privkey_export_encrypted_pbkdf_msec(botan_privkey_t key, uint8_t out[], size_t *out_len, botan_rng_t rng_obj, const char *pass, uint32_t pbkdf_msec, size_t *pbkdf_iters_out, const char *maybe_cipher, const char *maybe_pbkdf_hash, uint32_t flags)
Definition: ffi_pkey.cpp:185
int write_vec_output(uint8_t out[], size_t *out_len, const std::vector< uint8_t, Alloc > &buf)
Definition: ffi_util.h:146
std::vector< uint8_t > BER_encode_encrypted_pbkdf_msec(const Private_Key &key, RandomNumberGenerator &rng, const std::string &pass, std::chrono::milliseconds pbkdf_msec, size_t *pbkdf_iterations, const std::string &cipher, const std::string &pbkdf_hash)
Definition: pkcs8.cpp:294
int botan_privkey_algo_name(botan_privkey_t key, char out[], size_t *out_len)
Definition: ffi_pkey.cpp:126
int write_str_output(uint8_t out[], size_t *out_len, const std::string &str)
Definition: ffi_util.h:151
int botan_privkey_export_encrypted_pbkdf_iter(botan_privkey_t key, uint8_t out[], size_t *out_len, botan_rng_t rng_obj, const char *pass, size_t pbkdf_iter, const char *maybe_cipher, const char *maybe_pbkdf_hash, uint32_t flags)
Definition: ffi_pkey.cpp:219
int botan_pubkey_check_key(botan_pubkey_t key, botan_rng_t rng, uint32_t flags)
Definition: ffi_pkey.cpp:136
#define BOTAN_CHECK_KEY_EXPENSIVE_TESTS
Definition: ffi.h:944
#define BOTAN_PRIVKEY_EXPORT_FLAG_DER
Definition: ffi.h:1023
int botan_pubkey_load(botan_pubkey_t *key, const uint8_t bits[], size_t bits_len)
Definition: ffi_pkey.cpp:93
static std::unique_ptr< HashFunction > create(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:110
std::string PEM_encode(const Private_Key &key)
Definition: pkcs8.cpp:148
secure_vector< uint8_t > BER_encode(const Private_Key &key)
Definition: pkcs8.cpp:139
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition: ffi_util.h:120
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
struct botan_privkey_struct * botan_privkey_t
Definition: ffi.h:929
#define BOTAN_UNUSED(...)
Definition: assert.h:142
std::string PEM_encode_encrypted_pbkdf_iter(const Private_Key &key, RandomNumberGenerator &rng, const std::string &pass, size_t pbkdf_iterations, const std::string &cipher, const std::string &pbkdf_hash)
Definition: pkcs8.cpp:279
T & safe_get(botan_struct< T, M > *p)
Definition: ffi_util.h:61
int botan_pubkey_fingerprint(botan_pubkey_t key, const char *hash_fn, uint8_t out[], size_t *out_len)
Definition: ffi_pkey.cpp:256
virtual size_t estimated_strength() const =0
int botan_privkey_export(botan_privkey_t key, uint8_t out[], size_t *out_len, uint32_t flags)
Definition: ffi_pkey.cpp:163
int botan_pubkey_destroy(botan_pubkey_t key)
Definition: ffi_pkey.cpp:110
int botan_pubkey_estimated_strength(botan_pubkey_t key, size_t *estimate)
Definition: ffi_pkey.cpp:251
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:175
int botan_privkey_check_key(botan_privkey_t key, botan_rng_t rng, uint32_t flags)
Definition: ffi_pkey.cpp:144
struct botan_pubkey_struct * botan_pubkey_t
Definition: ffi.h:1076
int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t *out_len)
Definition: ffi_pkey.cpp:131
std::unique_ptr< Private_Key > load_key(DataSource &source, std::function< std::string()> get_pass)
Definition: pkcs8.cpp:366
int write_output(uint8_t out[], size_t *out_len, const uint8_t buf[], size_t buf_len)
Definition: ffi_util.h:122
#define BOTAN_FFI_DO(T, obj, param, block)
Definition: ffi_util.h:92
struct botan_rng_struct * botan_rng_t
Definition: ffi.h:188
int botan_pkcs_hash_id(const char *hash_name, uint8_t pkcs_id[], size_t *pkcs_id_len)
Definition: ffi_pkey.cpp:265
std::vector< uint8_t > pkcs_hash_id(const std::string &name)
Definition: hash_id.cpp:77
std::string PEM_encode_encrypted_pbkdf_msec(const Private_Key &key, RandomNumberGenerator &rng, const std::string &pass, std::chrono::milliseconds pbkdf_msec, size_t *pbkdf_iterations, const std::string &cipher, const std::string &pbkdf_hash)
Definition: pkcs8.cpp:327
Public_Key * load_key(DataSource &source)
Definition: x509_key.cpp:37