Botan 3.0.0
Crypto and TLS for C&
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
17namespace Botan_FFI {
18
19thread_local std::string g_last_exception_what;
20
21int ffi_error_exception_thrown(const char* func_name, const char* exn, int rc)
22 {
23 g_last_exception_what.assign(exn);
24
25 std::string val;
26 if(Botan::OS::read_env_variable(val, "BOTAN_FFI_PRINT_EXCEPTIONS") == true && !val.empty())
27 {
28 static_cast<void>(std::fprintf(stderr, "in %s exception '%s' returning %d\n", func_name, exn, rc));
29 }
30 return rc;
31 }
32
33int botan_view_str_bounce_fn(botan_view_ctx vctx, const char* str, size_t len)
34 {
35 return botan_view_bin_bounce_fn(vctx, reinterpret_cast<const uint8_t*>(str), len);
36 }
37
38int botan_view_bin_bounce_fn(botan_view_ctx vctx, const uint8_t* buf, size_t len)
39 {
40 if(vctx == nullptr || buf == nullptr)
42
43 botan_view_bounce_struct* ctx = static_cast<botan_view_bounce_struct*>(vctx);
44
45 const size_t avail = *ctx->out_len;
46 *ctx->out_len = len;
47
48 if(avail < len || ctx->out_ptr == nullptr)
49 {
50 if(ctx->out_ptr)
51 Botan::clear_mem(ctx->out_ptr, avail);
53 }
54 else
55 {
56 Botan::copy_mem(ctx->out_ptr, buf, len);
57 return BOTAN_FFI_SUCCESS;
58 }
59 }
60
61namespace {
62
63int ffi_map_error_type(Botan::ErrorType err)
64 {
65 switch(err)
66 {
69
80
94
98
101
106
113 }
114
116 }
117
118}
119
120int ffi_guard_thunk(const char* func_name, const std::function<int ()>& thunk)
121 {
122 g_last_exception_what.clear();
123
124 try
125 {
126 return thunk();
127 }
128 catch(std::bad_alloc&)
129 {
130 return ffi_error_exception_thrown(func_name, "bad_alloc", BOTAN_FFI_ERROR_OUT_OF_MEMORY);
131 }
132 catch(Botan_FFI::FFI_Error& e)
133 {
134 return ffi_error_exception_thrown(func_name, e.what(), e.error_code());
135 }
136 catch(Botan::Exception& e)
137 {
138 return ffi_error_exception_thrown(func_name, e.what(), ffi_map_error_type(e.error_type()));
139 }
140 catch(std::exception& e)
141 {
142 return ffi_error_exception_thrown(func_name, e.what());
143 }
144 catch(...)
145 {
146 return ffi_error_exception_thrown(func_name, "unknown exception");
147 }
148
150 }
151
152}
153
154extern "C" {
155
156using namespace Botan_FFI;
157
159 {
160 return g_last_exception_what.c_str();
161 }
162
163const char* botan_error_description(int err)
164 {
165 switch(err)
166 {
168 return "OK";
169
171 return "Invalid verifier";
172
174 return "Invalid input";
175
177 return "Invalid authentication code";
178
180 return "Insufficient buffer space";
181
183 return "String conversion error";
184
186 return "Exception thrown";
187
189 return "Out of memory";
190
192 return "Error while calling system API";
193
195 return "Internal error";
196
198 return "Bad flag";
199
201 return "Null pointer argument";
202
204 return "Bad parameter";
205
207 return "Key not set on object";
208
210 return "Invalid key length";
211
213 return "Invalid object state";
214
216 return "Not implemented";
217
219 return "Invalid object handle";
220
222 return "TLS error";
223
225 return "HTTP error";
226
228 return "Unknown error";
229
230 default:
231 return "Unknown error";
232 }
233 }
234
235/*
236* Versioning
237*/
239 {
240 return BOTAN_HAS_FFI;
241 }
242
243int botan_ffi_supports_api(uint32_t api_version)
244 {
245 // This is the API introduced in 3.0
246 if(api_version == 20230403)
247 return BOTAN_FFI_SUCCESS;
248
249 // This is the API introduced in 2.18
250 if(api_version == 20210220)
251 return BOTAN_FFI_SUCCESS;
252
253 // This is the API introduced in 2.13
254 if(api_version == 20191214)
255 return BOTAN_FFI_SUCCESS;
256
257 // This is the API introduced in 2.8
258 if(api_version == 20180713)
259 return BOTAN_FFI_SUCCESS;
260
261 // This is the API introduced in 2.3
262 if(api_version == 20170815)
263 return BOTAN_FFI_SUCCESS;
264
265 // This is the API introduced in 2.1
266 if(api_version == 20170327)
267 return BOTAN_FFI_SUCCESS;
268
269 // This is the API introduced in 2.0
270 if(api_version == 20150515)
271 return BOTAN_FFI_SUCCESS;
272
273 // Something else:
274 return -1;
275 }
276
278 {
279 return Botan::version_cstr();
280 }
281
286
287int botan_constant_time_compare(const uint8_t* x, const uint8_t* y, size_t len)
288 {
289 return Botan::constant_time_compare(x, y, len) ? 0 : -1;
290 }
291
292int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len)
293 {
294 return botan_constant_time_compare(x, y, len);
295 }
296
297int botan_scrub_mem(void* mem, size_t bytes)
298 {
299 Botan::secure_scrub_memory(mem, bytes);
300 return BOTAN_FFI_SUCCESS;
301 }
302
303int botan_hex_encode(const uint8_t* in, size_t len, char* out, uint32_t flags)
304 {
305 return ffi_guard_thunk(__func__, [=]() -> int {
306 const bool uppercase = (flags & BOTAN_FFI_HEX_LOWER_CASE) == 0;
307 Botan::hex_encode(out, in, len, uppercase);
308 return BOTAN_FFI_SUCCESS;
309 });
310 }
311
312int botan_hex_decode(const char* hex_str, size_t in_len, uint8_t* out, size_t* out_len)
313 {
314 return ffi_guard_thunk(__func__, [=]() -> int {
315 const std::vector<uint8_t> bin = Botan::hex_decode(hex_str, in_len);
316 return Botan_FFI::write_vec_output(out, out_len, bin);
317 });
318 }
319
320int botan_base64_encode(const uint8_t* in, size_t len, char* out, size_t* out_len)
321 {
322 return ffi_guard_thunk(__func__, [=]() -> int {
323 const std::string base64 = Botan::base64_encode(in, len);
324 return Botan_FFI::write_str_output(out, out_len, base64);
325 });
326 }
327
328int botan_base64_decode(const char* base64_str, size_t in_len,
329 uint8_t* out, size_t* out_len)
330 {
331 return ffi_guard_thunk(__func__, [=]() -> int {
332 if(*out_len < Botan::base64_decode_max_output(in_len))
333 {
334 *out_len = Botan::base64_decode_max_output(in_len);
336 }
337
338 *out_len = Botan::base64_decode(out, std::string(base64_str, in_len));
339 return BOTAN_FFI_SUCCESS;
340 });
341 }
342
343}
static SIMD_4x64 y
const char * what() const noexcept override
Definition: exceptn.h:94
Botan::ErrorType error_type() const noexcept override
Definition: ffi_util.h:29
int error_code() const noexcept override
Definition: ffi_util.h:27
uint32_t botan_version_datestamp()
Definition: ffi.cpp:285
int botan_same_mem(const uint8_t *x, const uint8_t *y, size_t len)
Definition: ffi.cpp:292
const char * botan_version_string()
Definition: ffi.cpp:277
int botan_base64_decode(const char *base64_str, size_t in_len, uint8_t *out, size_t *out_len)
Definition: ffi.cpp:328
uint32_t botan_version_patch()
Definition: ffi.cpp:284
int botan_base64_encode(const uint8_t *in, size_t len, char *out, size_t *out_len)
Definition: ffi.cpp:320
int botan_scrub_mem(void *mem, size_t bytes)
Definition: ffi.cpp:297
int botan_hex_encode(const uint8_t *in, size_t len, char *out, uint32_t flags)
Definition: ffi.cpp:303
uint32_t botan_version_major()
Definition: ffi.cpp:282
uint32_t botan_ffi_api_version()
Definition: ffi.cpp:238
int botan_ffi_supports_api(uint32_t api_version)
Definition: ffi.cpp:243
const char * botan_error_description(int err)
Definition: ffi.cpp:163
uint32_t botan_version_minor()
Definition: ffi.cpp:283
int botan_constant_time_compare(const uint8_t *x, const uint8_t *y, size_t len)
Definition: ffi.cpp:287
int botan_hex_decode(const char *hex_str, size_t in_len, uint8_t *out, size_t *out_len)
Definition: ffi.cpp:312
const char * botan_error_last_exception_message()
Definition: ffi.cpp:158
#define BOTAN_FFI_HEX_LOWER_CASE
Definition: ffi.h:192
void * botan_view_ctx
Definition: ffi.h:101
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition: ffi.h:91
@ BOTAN_FFI_ERROR_INVALID_KEY_LENGTH
Definition: ffi.h:88
@ BOTAN_FFI_ERROR_KEY_NOT_SET
Definition: ffi.h:87
@ BOTAN_FFI_ERROR_TLS_ERROR
Definition: ffi.h:94
@ BOTAN_FFI_ERROR_EXCEPTION_THROWN
Definition: ffi.h:79
@ BOTAN_FFI_ERROR_OUT_OF_MEMORY
Definition: ffi.h:80
@ BOTAN_FFI_ERROR_INTERNAL_ERROR
Definition: ffi.h:82
@ BOTAN_FFI_INVALID_VERIFIER
Definition: ffi.h:71
@ BOTAN_FFI_ERROR_INVALID_OBJECT
Definition: ffi.h:92
@ BOTAN_FFI_ERROR_UNKNOWN_ERROR
Definition: ffi.h:98
@ BOTAN_FFI_ERROR_HTTP_ERROR
Definition: ffi.h:95
@ BOTAN_FFI_ERROR_BAD_FLAG
Definition: ffi.h:84
@ BOTAN_FFI_ERROR_INVALID_INPUT
Definition: ffi.h:73
@ BOTAN_FFI_ERROR_STRING_CONVERSION_ERROR
Definition: ffi.h:77
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition: ffi.h:85
@ BOTAN_FFI_SUCCESS
Definition: ffi.h:70
@ BOTAN_FFI_ERROR_SYSTEM_ERROR
Definition: ffi.h:81
@ BOTAN_FFI_ERROR_ROUGHTIME_ERROR
Definition: ffi.h:96
@ BOTAN_FFI_ERROR_INVALID_OBJECT_STATE
Definition: ffi.h:89
@ BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE
Definition: ffi.h:76
@ BOTAN_FFI_ERROR_BAD_MAC
Definition: ffi.h:74
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition: ffi.h:86
#define BOTAN_HAS_FFI
Definition: build.h:208
bool read_env_variable(std::string &value_out, std::string_view var_name)
Definition: os_utils.cpp:422
int ffi_error_exception_thrown(const char *func_name, const char *exn, int rc)
Definition: ffi.cpp:21
int botan_view_bin_bounce_fn(botan_view_ctx vctx, const uint8_t *buf, size_t len)
Definition: ffi.cpp:38
int botan_view_str_bounce_fn(botan_view_ctx vctx, const char *str, size_t len)
Definition: ffi.cpp:33
int write_str_output(uint8_t out[], size_t *out_len, std::string_view str)
Definition: ffi_util.h:219
thread_local std::string g_last_exception_what
Definition: ffi.cpp:19
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
uint32_t version_minor()
Definition: version.cpp:83
uint32_t version_major()
Definition: version.cpp:82
const char * version_cstr()
Definition: version.cpp:35
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: base64.cpp:178
uint32_t version_datestamp()
Definition: version.cpp:77
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:126
void secure_scrub_memory(void *ptr, size_t n)
Definition: os_utils.cpp:81
uint32_t version_patch()
Definition: version.cpp:84
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:193
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:82
ErrorType
Definition: exceptn.h:20
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:33
size_t base64_decode_max_output(size_t input_length)
Definition: base64.cpp:246
size_t hex_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool ignore_ws)
Definition: hex.cpp:91
constexpr void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:115