Botan 2.19.5 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
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 {
35 case Botan::ErrorType::Unknown:
36 return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
37
38 case Botan::ErrorType::SystemError:
39 case Botan::ErrorType::IoError:
40 case Botan::ErrorType::OpenSSLError:
41 case Botan::ErrorType::Pkcs11Error:
42 case Botan::ErrorType::CommonCryptoError:
43 case Botan::ErrorType::TPMError:
44 case Botan::ErrorType::ZlibError:
45 case Botan::ErrorType::Bzip2Error:
46 case Botan::ErrorType::LzmaError:
47 case Botan::ErrorType::DatabaseError:
48 return BOTAN_FFI_ERROR_SYSTEM_ERROR;
49
50 case Botan::ErrorType::NotImplemented:
51 return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
52 case Botan::ErrorType::OutOfMemory:
53 return BOTAN_FFI_ERROR_OUT_OF_MEMORY;
54 case Botan::ErrorType::InternalError:
55 return BOTAN_FFI_ERROR_INTERNAL_ERROR;
56 case Botan::ErrorType::InvalidObjectState:
57 return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
58 case Botan::ErrorType::KeyNotSet:
59 return BOTAN_FFI_ERROR_KEY_NOT_SET;
60 case Botan::ErrorType::InvalidArgument:
61 case Botan::ErrorType::InvalidNonceLength:
62 return BOTAN_FFI_ERROR_BAD_PARAMETER;
63
64 case Botan::ErrorType::EncodingFailure:
65 case Botan::ErrorType::DecodingFailure:
66 return BOTAN_FFI_ERROR_INVALID_INPUT;
67
68 case Botan::ErrorType::InvalidTag:
69 return BOTAN_FFI_ERROR_BAD_MAC;
70
71 case Botan::ErrorType::InvalidKeyLength:
72 return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
73 case Botan::ErrorType::LookupError:
74 return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
75
76 case Botan::ErrorType::HttpError:
77 return BOTAN_FFI_ERROR_HTTP_ERROR;
78 case Botan::ErrorType::TLSError:
79 return BOTAN_FFI_ERROR_TLS_ERROR;
80 case Botan::ErrorType::RoughtimeError:
81 return BOTAN_FFI_ERROR_ROUGHTIME_ERROR;
82 }
83
84 return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
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
116 return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
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
132 case BOTAN_FFI_INVALID_VERIFIER:
133 return "Invalid verifier";
134
135 case BOTAN_FFI_ERROR_INVALID_INPUT:
136 return "Invalid input";
137
138 case BOTAN_FFI_ERROR_BAD_MAC:
139 return "Invalid authentication code";
140
141 case BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE:
142 return "Insufficient buffer space";
143
144 case BOTAN_FFI_ERROR_EXCEPTION_THROWN:
145 return "Exception thrown";
146
147 case BOTAN_FFI_ERROR_OUT_OF_MEMORY:
148 return "Out of memory";
149
150 case BOTAN_FFI_ERROR_SYSTEM_ERROR:
151 return "Error while calling system API";
152
153 case BOTAN_FFI_ERROR_INTERNAL_ERROR:
154 return "Internal error";
155
156 case BOTAN_FFI_ERROR_BAD_FLAG:
157 return "Bad flag";
158
159 case BOTAN_FFI_ERROR_NULL_POINTER:
160 return "Null pointer argument";
161
162 case BOTAN_FFI_ERROR_BAD_PARAMETER:
163 return "Bad parameter";
164
165 case BOTAN_FFI_ERROR_KEY_NOT_SET:
166 return "Key not set on object";
167
168 case BOTAN_FFI_ERROR_INVALID_KEY_LENGTH:
169 return "Invalid key length";
170
171 case BOTAN_FFI_ERROR_INVALID_OBJECT_STATE:
172 return "Invalid object state";
173
174 case BOTAN_FFI_ERROR_NOT_IMPLEMENTED:
175 return "Not implemented";
176
177 case BOTAN_FFI_ERROR_INVALID_OBJECT:
178 return "Invalid object handle";
179
180 case BOTAN_FFI_ERROR_TLS_ERROR:
181 return "TLS error";
182
183 case BOTAN_FFI_ERROR_HTTP_ERROR:
184 return "HTTP error";
185
186 case BOTAN_FFI_ERROR_UNKNOWN_ERROR:
187 return "Unknown error";
188 }
189
190 return "Unknown error";
191 }
192
193/*
194* Versioning
195*/
196uint32_t botan_ffi_api_version()
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.18
204 if(api_version == 20210220)
205 return BOTAN_FFI_SUCCESS;
206
207 // This is the API introduced in 2.13
208 if(api_version == 20191214)
209 return BOTAN_FFI_SUCCESS;
210
211 // This is the API introduced in 2.8
212 if(api_version == 20180713)
213 return BOTAN_FFI_SUCCESS;
214
215 // This is the API introduced in 2.3
216 if(api_version == 20170815)
217 return BOTAN_FFI_SUCCESS;
218
219 // This is the API introduced in 2.1
220 if(api_version == 20170327)
221 return BOTAN_FFI_SUCCESS;
222
223 // This is the API introduced in 2.0
224 if(api_version == 20150515)
225 return BOTAN_FFI_SUCCESS;
226
227 // Something else:
228 return -1;
229 }
230
231 const char* botan_version_string()
232 {
233 return Botan::version_cstr();
234 }
235
236uint32_t botan_version_major() { return Botan::version_major(); }
237uint32_t botan_version_minor() { return Botan::version_minor(); }
238uint32_t botan_version_patch() { return Botan::version_patch(); }
239uint32_t botan_version_datestamp() { return Botan::version_datestamp(); }
240
241 int botan_constant_time_compare(const uint8_t* x, const uint8_t* y, size_t len)
242 {
243 return Botan::constant_time_compare(x, y, len) ? 0 : -1;
244 }
245
246 int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len)
247 {
248 return botan_constant_time_compare(x, y, len);
249 }
250
251 int botan_scrub_mem(void* mem, size_t bytes)
252 {
253 Botan::secure_scrub_memory(mem, bytes);
254 return BOTAN_FFI_SUCCESS;
255 }
256
257 int botan_hex_encode(const uint8_t* in, size_t len, char* out, uint32_t flags)
258 {
259 return ffi_guard_thunk(__func__, [=]() -> int {
260 const bool uppercase = (flags & BOTAN_FFI_HEX_LOWER_CASE) == 0;
261 Botan::hex_encode(out, in, len, uppercase);
262 return BOTAN_FFI_SUCCESS;
263 });
264 }
265
266 int botan_hex_decode(const char* hex_str, size_t in_len, uint8_t* out, size_t* out_len)
267 {
268 return ffi_guard_thunk(__func__, [=]() -> int {
269 const std::vector<uint8_t> bin = Botan::hex_decode(hex_str, in_len);
270 return Botan_FFI::write_vec_output(out, out_len, bin);
271 });
272 }
273
274 int botan_base64_encode(const uint8_t* in, size_t len, char* out, size_t* out_len)
275 {
276 return ffi_guard_thunk(__func__, [=]() -> int {
277 const std::string base64 = Botan::base64_encode(in, len);
278 return Botan_FFI::write_str_output(out, out_len, base64);
279 });
280 }
281
282 int botan_base64_decode(const char* base64_str, size_t in_len,
283 uint8_t* out, size_t* out_len)
284 {
285 return ffi_guard_thunk(__func__, [=]() -> int {
286 if(*out_len < Botan::base64_decode_max_output(in_len))
287 {
288 *out_len = Botan::base64_decode_max_output(in_len);
289 return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
290 }
291
292 *out_len = Botan::base64_decode(out, std::string(base64_str, in_len));
293 return BOTAN_FFI_SUCCESS;
294 });
295 }
296
297}
Botan::Exception
Definition: exceptn.h:86
Botan::Exception::what
const char * what() const noexcept override
Definition: exceptn.h:96
Botan_FFI::FFI_Error
Definition: ffi_util.h:20
Botan_FFI::FFI_Error::error_type
Botan::ErrorType error_type() const noexcept override
Definition: ffi_util.h:29
Botan_FFI::FFI_Error::error_code
int error_code() const noexcept override
Definition: ffi_util.h:27
botan_version_datestamp
uint32_t botan_version_datestamp()
Definition: ffi.cpp:239
botan_same_mem
int botan_same_mem(const uint8_t *x, const uint8_t *y, size_t len)
Definition: ffi.cpp:246
botan_version_string
const char * botan_version_string()
Definition: ffi.cpp:231
botan_base64_decode
int botan_base64_decode(const char *base64_str, size_t in_len, uint8_t *out, size_t *out_len)
Definition: ffi.cpp:282
botan_version_patch
uint32_t botan_version_patch()
Definition: ffi.cpp:238
botan_base64_encode
int botan_base64_encode(const uint8_t *in, size_t len, char *out, size_t *out_len)
Definition: ffi.cpp:274
botan_scrub_mem
int botan_scrub_mem(void *mem, size_t bytes)
Definition: ffi.cpp:251
botan_hex_encode
int botan_hex_encode(const uint8_t *in, size_t len, char *out, uint32_t flags)
Definition: ffi.cpp:257
botan_version_major
uint32_t botan_version_major()
Definition: ffi.cpp:236
botan_ffi_api_version
uint32_t botan_ffi_api_version()
Definition: ffi.cpp:196
botan_ffi_supports_api
int botan_ffi_supports_api(uint32_t api_version)
Definition: ffi.cpp:201
botan_error_description
const char * botan_error_description(int err)
Definition: ffi.cpp:125
botan_version_minor
uint32_t botan_version_minor()
Definition: ffi.cpp:237
botan_constant_time_compare
int botan_constant_time_compare(const uint8_t *x, const uint8_t *y, size_t len)
Definition: ffi.cpp:241
botan_hex_decode
int botan_hex_decode(const char *hex_str, size_t in_len, uint8_t *out, size_t *out_len)
Definition: ffi.cpp:266
BOTAN_FFI_HEX_LOWER_CASE
#define BOTAN_FFI_HEX_LOWER_CASE
Definition: ffi.h:154
BOTAN_FFI_ERROR_NOT_IMPLEMENTED
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition: ffi.h:83
BOTAN_FFI_ERROR_INVALID_KEY_LENGTH
@ BOTAN_FFI_ERROR_INVALID_KEY_LENGTH
Definition: ffi.h:80
BOTAN_FFI_ERROR_KEY_NOT_SET
@ BOTAN_FFI_ERROR_KEY_NOT_SET
Definition: ffi.h:79
BOTAN_FFI_ERROR_TLS_ERROR
@ BOTAN_FFI_ERROR_TLS_ERROR
Definition: ffi.h:86
BOTAN_FFI_ERROR_EXCEPTION_THROWN
@ BOTAN_FFI_ERROR_EXCEPTION_THROWN
Definition: ffi.h:71
BOTAN_FFI_ERROR_OUT_OF_MEMORY
@ BOTAN_FFI_ERROR_OUT_OF_MEMORY
Definition: ffi.h:72
BOTAN_FFI_ERROR_INTERNAL_ERROR
@ BOTAN_FFI_ERROR_INTERNAL_ERROR
Definition: ffi.h:74
BOTAN_FFI_INVALID_VERIFIER
@ BOTAN_FFI_INVALID_VERIFIER
Definition: ffi.h:64
BOTAN_FFI_ERROR_INVALID_OBJECT
@ BOTAN_FFI_ERROR_INVALID_OBJECT
Definition: ffi.h:84
BOTAN_FFI_ERROR_UNKNOWN_ERROR
@ BOTAN_FFI_ERROR_UNKNOWN_ERROR
Definition: ffi.h:90
BOTAN_FFI_ERROR_HTTP_ERROR
@ BOTAN_FFI_ERROR_HTTP_ERROR
Definition: ffi.h:87
BOTAN_FFI_ERROR_BAD_FLAG
@ BOTAN_FFI_ERROR_BAD_FLAG
Definition: ffi.h:76
BOTAN_FFI_ERROR_INVALID_INPUT
@ BOTAN_FFI_ERROR_INVALID_INPUT
Definition: ffi.h:66
BOTAN_FFI_ERROR_NULL_POINTER
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition: ffi.h:77
BOTAN_FFI_SUCCESS
@ BOTAN_FFI_SUCCESS
Definition: ffi.h:63
BOTAN_FFI_ERROR_SYSTEM_ERROR
@ BOTAN_FFI_ERROR_SYSTEM_ERROR
Definition: ffi.h:73
BOTAN_FFI_ERROR_ROUGHTIME_ERROR
@ BOTAN_FFI_ERROR_ROUGHTIME_ERROR
Definition: ffi.h:88
BOTAN_FFI_ERROR_INVALID_OBJECT_STATE
@ BOTAN_FFI_ERROR_INVALID_OBJECT_STATE
Definition: ffi.h:81
BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE
@ BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE
Definition: ffi.h:69
BOTAN_FFI_ERROR_BAD_MAC
@ BOTAN_FFI_ERROR_BAD_MAC
Definition: ffi.h:67
BOTAN_FFI_ERROR_BAD_PARAMETER
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition: ffi.h:78
Botan::OS::read_env_variable
bool read_env_variable(std::string &value_out, const std::string &var_name)
Definition: os_utils.cpp:387
Botan::PKCS11::flags
Flags flags(Flag flags)
Definition: p11.h:860
Botan_FFI
Definition: ffi.cpp:17
Botan_FFI::ffi_error_exception_thrown
int ffi_error_exception_thrown(const char *func_name, const char *exn, int rc)
Definition: ffi.cpp:19
Botan_FFI::ffi_guard_thunk
int ffi_guard_thunk(const char *func_name, std::function< int()> thunk)
Definition: ffi.cpp:89
Botan_FFI::write_str_output
int write_str_output(uint8_t out[], size_t *out_len, const std::string &str)
Definition: ffi_util.h:160
Botan_FFI::write_vec_output
int write_vec_output(uint8_t out[], size_t *out_len, const std::vector< uint8_t, Alloc > &buf)
Definition: ffi_util.h:155
Botan::version_minor
uint32_t version_minor()
Definition: version.cpp:81
Botan::version_major
uint32_t version_major()
Definition: version.cpp:80
Botan::version_cstr
const char * version_cstr()
Definition: version.cpp:33
Botan::base64_encode
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
Botan::version_datestamp
uint32_t version_datestamp()
Definition: version.cpp:75
Botan::secure_scrub_memory
void secure_scrub_memory(void *ptr, size_t n)
Definition: os_utils.cpp:66
Botan::version_patch
uint32_t version_patch()
Definition: version.cpp:82
Botan::base64_decode
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
Botan::constant_time_compare
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:82
Botan::ErrorType
ErrorType
Definition: exceptn.h:20
Botan::ErrorType::InvalidNonceLength
@ InvalidNonceLength
Botan::ErrorType::EncodingFailure
@ EncodingFailure
Botan::ErrorType::InvalidArgument
@ InvalidArgument
Botan::ErrorType::HttpError
@ HttpError
Botan::ErrorType::Pkcs11Error
@ Pkcs11Error
Botan::ErrorType::CommonCryptoError
@ CommonCryptoError
Botan::ErrorType::DecodingFailure
@ DecodingFailure
Botan::ErrorType::KeyNotSet
@ KeyNotSet
Botan::ErrorType::InternalError
@ InternalError
Botan::ErrorType::Unknown
@ Unknown
Botan::ErrorType::NotImplemented
@ NotImplemented
Botan::ErrorType::DatabaseError
@ DatabaseError
Botan::ErrorType::OpenSSLError
@ OpenSSLError
Botan::ErrorType::TLSError
@ TLSError
Botan::ErrorType::InvalidObjectState
@ InvalidObjectState
Botan::ErrorType::LzmaError
@ LzmaError
Botan::ErrorType::ZlibError
@ ZlibError
Botan::ErrorType::OutOfMemory
@ OutOfMemory
Botan::ErrorType::SystemError
@ SystemError
Botan::ErrorType::Bzip2Error
@ Bzip2Error
Botan::ErrorType::LookupError
@ LookupError
Botan::ErrorType::InvalidKeyLength
@ InvalidKeyLength
Botan::ErrorType::IoError
@ IoError
Botan::ErrorType::InvalidTag
@ InvalidTag
Botan::ErrorType::RoughtimeError
@ RoughtimeError
Botan::ErrorType::TPMError
@ TPMError
Botan::hex_encode
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:31
Botan::base64_decode_max_output
size_t base64_decode_max_output(size_t input_length)
Definition: base64.cpp:243
Botan::hex_decode
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