Botan 3.0.0-alpha0
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 std::fprintf(stderr, "in %s exception '%s' returning %d\n", func_name, exn, rc);
29 }
30 return rc;
31 }
32
33namespace {
34
35int ffi_map_error_type(Botan::ErrorType err)
36 {
37 switch(err)
38 {
41
52
66
70
73
78
85 }
86
88 }
89
90}
91
92int ffi_guard_thunk(const char* func_name, const std::function<int ()>& thunk)
93 {
95
96 try
97 {
98 return thunk();
99 }
100 catch(std::bad_alloc&)
101 {
102 return ffi_error_exception_thrown(func_name, "bad_alloc", BOTAN_FFI_ERROR_OUT_OF_MEMORY);
103 }
104 catch(Botan_FFI::FFI_Error& e)
105 {
106 return ffi_error_exception_thrown(func_name, e.what(), e.error_code());
107 }
108 catch(Botan::Exception& e)
109 {
110 return ffi_error_exception_thrown(func_name, e.what(), ffi_map_error_type(e.error_type()));
111 }
112 catch(std::exception& e)
113 {
114 return ffi_error_exception_thrown(func_name, e.what());
115 }
116 catch(...)
117 {
118 return ffi_error_exception_thrown(func_name, "unknown exception");
119 }
120
122 }
123
124}
125
126extern "C" {
127
128using namespace Botan_FFI;
129
131 {
132 return g_last_exception_what.c_str();
133 }
134
135const char* botan_error_description(int err)
136 {
137 switch(err)
138 {
140 return "OK";
141
143 return "Invalid verifier";
144
146 return "Invalid input";
147
149 return "Invalid authentication code";
150
152 return "Insufficient buffer space";
153
155 return "Exception thrown";
156
158 return "Out of memory";
159
161 return "Error while calling system API";
162
164 return "Internal error";
165
167 return "Bad flag";
168
170 return "Null pointer argument";
171
173 return "Bad parameter";
174
176 return "Key not set on object";
177
179 return "Invalid key length";
180
182 return "Invalid object state";
183
185 return "Not implemented";
186
188 return "Invalid object handle";
189
191 return "TLS error";
192
194 return "HTTP error";
195
197 return "Unknown error";
198 }
199
200 return "Unknown error";
201 }
202
203/*
204* Versioning
205*/
207 {
208 return BOTAN_HAS_FFI;
209 }
210
211int botan_ffi_supports_api(uint32_t api_version)
212 {
213 // This is the API introduced in 3.0
214 if(api_version == 20210628)
215 return BOTAN_FFI_SUCCESS;
216
217 // This is the API introduced in 2.18
218 if(api_version == 20210220)
219 return BOTAN_FFI_SUCCESS;
220
221 // This is the API introduced in 2.13
222 if(api_version == 20191214)
223 return BOTAN_FFI_SUCCESS;
224
225 // This is the API introduced in 2.8
226 if(api_version == 20180713)
227 return BOTAN_FFI_SUCCESS;
228
229 // This is the API introduced in 2.3
230 if(api_version == 20170815)
231 return BOTAN_FFI_SUCCESS;
232
233 // This is the API introduced in 2.1
234 if(api_version == 20170327)
235 return BOTAN_FFI_SUCCESS;
236
237 // This is the API introduced in 2.0
238 if(api_version == 20150515)
239 return BOTAN_FFI_SUCCESS;
240
241 // Something else:
242 return -1;
243 }
244
246 {
247 return Botan::version_cstr();
248 }
249
254
255int botan_constant_time_compare(const uint8_t* x, const uint8_t* y, size_t len)
256 {
257 return Botan::constant_time_compare(x, y, len) ? 0 : -1;
258 }
259
260int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len)
261 {
262 return botan_constant_time_compare(x, y, len);
263 }
264
265int botan_scrub_mem(void* mem, size_t bytes)
266 {
267 Botan::secure_scrub_memory(mem, bytes);
268 return BOTAN_FFI_SUCCESS;
269 }
270
271int botan_hex_encode(const uint8_t* in, size_t len, char* out, uint32_t flags)
272 {
273 return ffi_guard_thunk(__func__, [=]() -> int {
274 const bool uppercase = (flags & BOTAN_FFI_HEX_LOWER_CASE) == 0;
275 Botan::hex_encode(out, in, len, uppercase);
276 return BOTAN_FFI_SUCCESS;
277 });
278 }
279
280int botan_hex_decode(const char* hex_str, size_t in_len, uint8_t* out, size_t* out_len)
281 {
282 return ffi_guard_thunk(__func__, [=]() -> int {
283 const std::vector<uint8_t> bin = Botan::hex_decode(hex_str, in_len);
284 return Botan_FFI::write_vec_output(out, out_len, bin);
285 });
286 }
287
288int botan_base64_encode(const uint8_t* in, size_t len, char* out, size_t* out_len)
289 {
290 return ffi_guard_thunk(__func__, [=]() -> int {
291 const std::string base64 = Botan::base64_encode(in, len);
292 return Botan_FFI::write_str_output(out, out_len, base64);
293 });
294 }
295
296int botan_base64_decode(const char* base64_str, size_t in_len,
297 uint8_t* out, size_t* out_len)
298 {
299 return ffi_guard_thunk(__func__, [=]() -> int {
300 if(*out_len < Botan::base64_decode_max_output(in_len))
301 {
302 *out_len = Botan::base64_decode_max_output(in_len);
304 }
305
306 *out_len = Botan::base64_decode(out, std::string(base64_str, in_len));
307 return BOTAN_FFI_SUCCESS;
308 });
309 }
310
311}
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:253
int botan_same_mem(const uint8_t *x, const uint8_t *y, size_t len)
Definition: ffi.cpp:260
const char * botan_version_string()
Definition: ffi.cpp:245
int botan_base64_decode(const char *base64_str, size_t in_len, uint8_t *out, size_t *out_len)
Definition: ffi.cpp:296
uint32_t botan_version_patch()
Definition: ffi.cpp:252
int botan_base64_encode(const uint8_t *in, size_t len, char *out, size_t *out_len)
Definition: ffi.cpp:288
int botan_scrub_mem(void *mem, size_t bytes)
Definition: ffi.cpp:265
int botan_hex_encode(const uint8_t *in, size_t len, char *out, uint32_t flags)
Definition: ffi.cpp:271
uint32_t botan_version_major()
Definition: ffi.cpp:250
uint32_t botan_ffi_api_version()
Definition: ffi.cpp:206
int botan_ffi_supports_api(uint32_t api_version)
Definition: ffi.cpp:211
const char * botan_error_description(int err)
Definition: ffi.cpp:135
uint32_t botan_version_minor()
Definition: ffi.cpp:251
int botan_constant_time_compare(const uint8_t *x, const uint8_t *y, size_t len)
Definition: ffi.cpp:255
int botan_hex_decode(const char *hex_str, size_t in_len, uint8_t *out, size_t *out_len)
Definition: ffi.cpp:280
const char * botan_error_last_exception_message()
Definition: ffi.cpp:130
#define BOTAN_FFI_HEX_LOWER_CASE
Definition: ffi.h:163
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition: ffi.h:83
@ BOTAN_FFI_ERROR_INVALID_KEY_LENGTH
Definition: ffi.h:80
@ BOTAN_FFI_ERROR_KEY_NOT_SET
Definition: ffi.h:79
@ BOTAN_FFI_ERROR_TLS_ERROR
Definition: ffi.h:86
@ BOTAN_FFI_ERROR_EXCEPTION_THROWN
Definition: ffi.h:71
@ BOTAN_FFI_ERROR_OUT_OF_MEMORY
Definition: ffi.h:72
@ BOTAN_FFI_ERROR_INTERNAL_ERROR
Definition: ffi.h:74
@ BOTAN_FFI_INVALID_VERIFIER
Definition: ffi.h:64
@ BOTAN_FFI_ERROR_INVALID_OBJECT
Definition: ffi.h:84
@ BOTAN_FFI_ERROR_UNKNOWN_ERROR
Definition: ffi.h:90
@ BOTAN_FFI_ERROR_HTTP_ERROR
Definition: ffi.h:87
@ BOTAN_FFI_ERROR_BAD_FLAG
Definition: ffi.h:76
@ BOTAN_FFI_ERROR_INVALID_INPUT
Definition: ffi.h:66
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition: ffi.h:77
@ BOTAN_FFI_SUCCESS
Definition: ffi.h:63
@ BOTAN_FFI_ERROR_SYSTEM_ERROR
Definition: ffi.h:73
@ BOTAN_FFI_ERROR_ROUGHTIME_ERROR
Definition: ffi.h:88
@ BOTAN_FFI_ERROR_INVALID_OBJECT_STATE
Definition: ffi.h:81
@ BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE
Definition: ffi.h:69
@ BOTAN_FFI_ERROR_BAD_MAC
Definition: ffi.h:67
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition: ffi.h:78
#define BOTAN_HAS_FFI
Definition: build.h:206
bool read_env_variable(std::string &value_out, const std::string &var_name)
Definition: os_utils.cpp:452
Flags flags(Flag flags)
Definition: p11.h:860
int ffi_error_exception_thrown(const char *func_name, const char *exn, int rc)
Definition: ffi.cpp:21
thread_local std::string g_last_exception_what
Definition: ffi.cpp:19
int write_str_output(uint8_t out[], size_t *out_len, const std::string &str)
Definition: ffi_util.h:157
int ffi_guard_thunk(const char *func_name, const std::function< int()> &thunk)
Definition: ffi.cpp:92
int write_vec_output(uint8_t out[], size_t *out_len, const std::vector< uint8_t, Alloc > &buf)
Definition: ffi_util.h:152
uint32_t version_minor()
Definition: version.cpp:81
uint32_t version_major()
Definition: version.cpp:80
const char * version_cstr()
Definition: version.cpp:33
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: base64.cpp:185
uint32_t version_datestamp()
Definition: version.cpp:75
void secure_scrub_memory(void *ptr, size_t n)
Definition: os_utils.cpp:81
uint32_t version_patch()
Definition: version.cpp:82
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:200
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:31
size_t base64_decode_max_output(size_t input_length)
Definition: base64.cpp:243
size_t hex_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool ignore_ws)
Definition: hex.cpp:89