Botan  2.15.0
Crypto and TLS for C++11
ffi.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/os_utils.h>
10 #include <botan/version.h>
11 #include <botan/mem_ops.h>
12 #include <botan/hex.h>
13 #include <botan/base64.h>
14 #include <cstdio>
15 #include <cstdlib>
16 
17 namespace Botan_FFI {
18 
19 int ffi_error_exception_thrown(const char* func_name, const char* exn, int rc)
20  {
21  std::string val;
22  if(Botan::OS::read_env_variable(val, "BOTAN_FFI_PRINT_EXCEPTIONS") == true && val != "")
23  {
24  std::fprintf(stderr, "in %s exception '%s' returning %d\n", func_name, exn, rc);
25  }
26  return rc;
27  }
28 
29 namespace {
30 
31 int ffi_map_error_type(Botan::ErrorType err)
32  {
33  switch(err)
34  {
37 
49 
63 
67 
70 
75 
82  }
83 
85  }
86 
87 }
88 
89 int ffi_guard_thunk(const char* func_name, std::function<int ()> thunk)
90  {
91  try
92  {
93  return thunk();
94  }
95  catch(std::bad_alloc&)
96  {
97  return ffi_error_exception_thrown(func_name, "bad_alloc", BOTAN_FFI_ERROR_OUT_OF_MEMORY);
98  }
99  catch(Botan_FFI::FFI_Error& e)
100  {
101  return ffi_error_exception_thrown(func_name, e.what(), e.error_code());
102  }
103  catch(Botan::Exception& e)
104  {
105  return ffi_error_exception_thrown(func_name, e.what(), ffi_map_error_type(e.error_type()));
106  }
107  catch(std::exception& e)
108  {
109  return ffi_error_exception_thrown(func_name, e.what());
110  }
111  catch(...)
112  {
113  return ffi_error_exception_thrown(func_name, "unknown exception");
114  }
115 
117  }
118 
119 }
120 
121 extern "C" {
122 
123 using namespace Botan_FFI;
124 
125 const char* botan_error_description(int err)
126  {
127  switch(err)
128  {
129  case BOTAN_FFI_SUCCESS:
130  return "OK";
131 
133  return "Invalid verifier";
134 
136  return "Invalid input";
137 
139  return "Invalid authentication code";
140 
142  return "Insufficient buffer space";
143 
145  return "Exception thrown";
146 
148  return "Out of memory";
149 
151  return "Error while calling system API";
152 
154  return "Internal error";
155 
157  return "Bad flag";
158 
160  return "Null pointer argument";
161 
163  return "Bad parameter";
164 
166  return "Key not set on object";
167 
169  return "Invalid key length";
170 
172  return "Invalid object state";
173 
175  return "Not implemented";
176 
178  return "Invalid object handle";
179 
181  return "TLS error";
182 
184  return "HTTP error";
185 
187  return "Unknown error";
188  }
189 
190  return "Unknown error";
191  }
192 
193 /*
194 * Versioning
195 */
197  {
198  return BOTAN_HAS_FFI;
199  }
200 
201 int botan_ffi_supports_api(uint32_t api_version)
202  {
203  // This is the API introduced in 2.13
204  if(api_version == 20191214)
205  return BOTAN_FFI_SUCCESS;
206 
207  // This is the API introduced in 2.8
208  if(api_version == 20180713)
209  return BOTAN_FFI_SUCCESS;
210 
211  // This is the API introduced in 2.3
212  if(api_version == 20170815)
213  return BOTAN_FFI_SUCCESS;
214 
215  // This is the API introduced in 2.1
216  if(api_version == 20170327)
217  return BOTAN_FFI_SUCCESS;
218 
219  // This is the API introduced in 2.0
220  if(api_version == 20150515)
221  return BOTAN_FFI_SUCCESS;
222 
223  // Something else:
224  return -1;
225  }
226 
227 const char* botan_version_string()
228  {
229  return Botan::version_cstr();
230  }
231 
236 
237 int botan_constant_time_compare(const uint8_t* x, const uint8_t* y, size_t len)
238  {
239  return Botan::constant_time_compare(x, y, len) ? 0 : -1;
240  }
241 
242 int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len)
243  {
244  return botan_constant_time_compare(x, y, len);
245  }
246 
247 int botan_scrub_mem(void* mem, size_t bytes)
248  {
249  Botan::secure_scrub_memory(mem, bytes);
250  return BOTAN_FFI_SUCCESS;
251  }
252 
253 int botan_hex_encode(const uint8_t* in, size_t len, char* out, uint32_t flags)
254  {
255  return ffi_guard_thunk(__func__, [=]() -> int {
256  const bool uppercase = (flags & BOTAN_FFI_HEX_LOWER_CASE) == 0;
257  Botan::hex_encode(out, in, len, uppercase);
258  return BOTAN_FFI_SUCCESS;
259  });
260  }
261 
262 int botan_hex_decode(const char* hex_str, size_t in_len, uint8_t* out, size_t* out_len)
263  {
264  return ffi_guard_thunk(__func__, [=]() -> int {
265  const std::vector<uint8_t> bin = Botan::hex_decode(hex_str, in_len);
266  return Botan_FFI::write_vec_output(out, out_len, bin);
267  });
268  }
269 
270 int botan_base64_encode(const uint8_t* in, size_t len, char* out, size_t* out_len)
271  {
272  return ffi_guard_thunk(__func__, [=]() -> int {
273  const std::string base64 = Botan::base64_encode(in, len);
274  return Botan_FFI::write_str_output(out, out_len, base64);
275  });
276  }
277 
278 int botan_base64_decode(const char* base64_str, size_t in_len,
279  uint8_t* out, size_t* out_len)
280  {
281  return ffi_guard_thunk(__func__, [=]() -> int {
282  if(*out_len < Botan::base64_decode_max_output(in_len))
283  {
284  *out_len = Botan::base64_decode_max_output(in_len);
286  }
287 
288  *out_len = Botan::base64_decode(out, std::string(base64_str, in_len));
289  return BOTAN_FFI_SUCCESS;
290  });
291  }
292 
293 }
int ffi_guard_thunk(const char *func_name, std::function< int()> thunk)
Definition: ffi.cpp:89
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14
int botan_hex_encode(const uint8_t *in, size_t len, char *out, uint32_t flags)
Definition: ffi.cpp:253
bool read_env_variable(std::string &value_out, const std::string &var_name)
Definition: os_utils.cpp:387
int ffi_error_exception_thrown(const char *func_name, const char *exn, int rc)
Definition: ffi.cpp:19
size_t base64_decode_max_output(size_t input_length)
Definition: base64.cpp:224
virtual ErrorType error_type() const noexcept
Definition: exceptn.h:101
Flags flags(Flag flags)
Definition: p11.h:858
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:82
int write_vec_output(uint8_t out[], size_t *out_len, const std::vector< uint8_t, Alloc > &buf)
Definition: ffi_util.h:155
#define BOTAN_FFI_HEX_LOWER_CASE
Definition: ffi.h:153
int error_code() const noexcept override
Definition: ffi_util.h:27
const char * what() const noexcept override
Definition: exceptn.h:96
int botan_base64_encode(const uint8_t *in, size_t len, char *out, size_t *out_len)
Definition: ffi.cpp:270
uint32_t botan_version_patch()
Definition: ffi.cpp:234
int botan_scrub_mem(void *mem, size_t bytes)
Definition: ffi.cpp:247
uint32_t version_major()
Definition: version.cpp:72
int write_str_output(uint8_t out[], size_t *out_len, const std::string &str)
Definition: ffi_util.h:160
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: base64.cpp:166
uint32_t botan_ffi_api_version()
Definition: ffi.cpp:196
uint32_t version_patch()
Definition: version.cpp:74
ErrorType
Definition: exceptn.h:20
uint32_t botan_version_major()
Definition: ffi.cpp:232
int botan_same_mem(const uint8_t *x, const uint8_t *y, size_t len)
Definition: ffi.cpp:242
uint32_t version_minor()
Definition: version.cpp:73
size_t hex_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool ignore_ws)
Definition: hex.cpp:49
const char * botan_error_description(int err)
Definition: ffi.cpp:125
uint32_t botan_version_minor()
Definition: ffi.cpp:233
uint32_t version_datestamp()
Definition: version.cpp:67
int botan_base64_decode(const char *base64_str, size_t in_len, uint8_t *out, size_t *out_len)
Definition: ffi.cpp:278
void secure_scrub_memory(void *ptr, size_t n)
Definition: os_utils.cpp:66
size_t base64_decode(uint8_t out[], const char in[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
Definition: base64.cpp:181
uint32_t botan_version_datestamp()
Definition: ffi.cpp:235
int botan_hex_decode(const char *hex_str, size_t in_len, uint8_t *out, size_t *out_len)
Definition: ffi.cpp:262
int botan_ffi_supports_api(uint32_t api_version)
Definition: ffi.cpp:201
int botan_constant_time_compare(const uint8_t *x, const uint8_t *y, size_t len)
Definition: ffi.cpp:237
const char * version_cstr()
Definition: version.cpp:29
const char * botan_version_string()
Definition: ffi.cpp:227