Botan 3.13.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
9#include <botan/base64.h>
10#include <botan/hex.h>
11#include <botan/mem_ops.h>
12#include <botan/version.h>
13#include <botan/internal/ct_utils.h>
14#include <botan/internal/ffi_util.h>
15#include <cstdio>
16
17#if defined(BOTAN_HAS_OS_UTILS)
18 #include <botan/internal/os_utils.h>
19#endif
20
21namespace Botan_FFI {
22
23namespace {
24
25// NOLINTNEXTLINE(*-avoid-non-const-global-variables)
26thread_local std::string g_last_exception_what;
27
28int ffi_map_error_type(Botan::ErrorType err) {
29 switch(err) {
32
42
45
59
63
66
71
78 }
79
81}
82
83} // namespace
84
86 g_last_exception_what.clear();
87}
88
89int ffi_error_exception_thrown(const char* func_name, const char* exn, int rc) {
90 g_last_exception_what.assign(exn);
91
92#if defined(BOTAN_HAS_OS_UTILS)
93 std::string val;
94 if(Botan::OS::read_env_variable(val, "BOTAN_FFI_PRINT_EXCEPTIONS") && !val.empty()) {
95 // NOLINTNEXTLINE(*-vararg)
96 static_cast<void>(std::fprintf(stderr, "in %s exception '%s' returning %d\n", func_name, exn, rc));
97 }
98#endif
99
100 return rc;
101}
102
103int ffi_error_exception_thrown(const char* func_name, const char* exn, Botan::ErrorType err) {
104 return ffi_error_exception_thrown(func_name, exn, ffi_map_error_type(err));
105}
106
107int botan_view_str_bounce_fn(botan_view_ctx vctx, const char* str, size_t len) {
108 return botan_view_bin_bounce_fn(vctx, reinterpret_cast<const uint8_t*>(str), len);
109}
110
111int botan_view_bin_bounce_fn(botan_view_ctx vctx, const uint8_t* buf, size_t len) {
112 if(any_null_pointers(vctx, buf)) {
114 }
115
116 const botan_view_bounce_struct* ctx = static_cast<botan_view_bounce_struct*>(vctx);
117
118 if(ctx->out_len == nullptr) {
120 }
121
122 const size_t avail = *ctx->out_len;
123 *ctx->out_len = len;
124
125 if(avail < len || ctx->out_ptr == nullptr) {
126 if(ctx->out_ptr != nullptr) {
127 Botan::clear_mem(ctx->out_ptr, avail);
128 }
130 } else {
131 Botan::copy_mem(ctx->out_ptr, buf, len);
132 return BOTAN_FFI_SUCCESS;
133 }
134}
135
136} // namespace Botan_FFI
137
138extern "C" {
139
140using namespace Botan_FFI;
141
143 return g_last_exception_what.c_str();
144}
145
146const char* botan_error_description(int err) {
147 switch(err) {
149 return "OK";
150
152 return "Invalid verifier";
153
155 return "Invalid input";
156
158 return "Invalid authentication code";
159
161 return "No value available";
162
164 return "Insufficient buffer space";
165
167 return "String conversion error";
168
170 return "Exception thrown";
171
173 return "Out of memory";
174
176 return "Error while calling system API";
177
179 return "Internal error";
180
182 return "Bad flag";
183
185 return "Null pointer argument";
186
188 return "Bad parameter";
189
191 return "Key not set on object";
192
194 return "Invalid key length";
195
197 return "Invalid object state";
198
200 return "Index out of range";
201
203 return "Not implemented";
204
206 return "Invalid object handle";
207
209 return "TLS error";
210
212 return "HTTP error";
213
215 default:
216 return "Unknown error";
217 }
218}
219
220/*
221* Versioning
222*/
224 return BOTAN_HAS_FFI;
225}
226
227int botan_ffi_supports_api(uint32_t api_version) {
228 // This is the API introduced in 3.13
229 if(api_version == 20260811) {
230 return BOTAN_FFI_SUCCESS;
231 }
232
233 // This is the API introduced in 3.12
234 if(api_version == 20260506) {
235 return BOTAN_FFI_SUCCESS;
236 }
237
238 // This is the API introduced in 3.11
239 if(api_version == 20260303) {
240 return BOTAN_FFI_SUCCESS;
241 }
242
243 // This is the API introduced in 3.10
244 if(api_version == 20250829) {
245 return BOTAN_FFI_SUCCESS;
246 }
247
248 // This is the API introduced in 3.8
249 if(api_version == 20250506) {
250 return BOTAN_FFI_SUCCESS;
251 }
252
253 // This is the API introduced in 3.4
254 if(api_version == 20240408) {
255 return BOTAN_FFI_SUCCESS;
256 }
257
258 // This is the API introduced in 3.2
259 if(api_version == 20231009) {
260 return BOTAN_FFI_SUCCESS;
261 }
262
263 // This is the API introduced in 3.1
264 if(api_version == 20230711) {
265 return BOTAN_FFI_SUCCESS;
266 }
267
268 // This is the API introduced in 3.0
269 if(api_version == 20230403) {
270 return BOTAN_FFI_SUCCESS;
271 }
272
273 // This is the API introduced in 2.18
274 if(api_version == 20210220) {
275 return BOTAN_FFI_SUCCESS;
276 }
277
278 // This is the API introduced in 2.13
279 if(api_version == 20191214) {
280 return BOTAN_FFI_SUCCESS;
281 }
282
283 // This is the API introduced in 2.8
284 if(api_version == 20180713) {
285 return BOTAN_FFI_SUCCESS;
286 }
287
288 // This is the API introduced in 2.3
289 if(api_version == 20170815) {
290 return BOTAN_FFI_SUCCESS;
291 }
292
293 // This is the API introduced in 2.1
294 if(api_version == 20170327) {
295 return BOTAN_FFI_SUCCESS;
296 }
297
298 // This is the API introduced in 2.0
299 if(api_version == 20150515) {
300 return BOTAN_FFI_SUCCESS;
301 }
302
303 // Something else:
304 return -1;
305}
306
307const char* botan_version_string() {
308 return Botan::version_cstr();
309}
310
312 return Botan::version_major();
313}
314
316 return Botan::version_minor();
317}
318
320 return Botan::version_patch();
321}
322
325}
326
327int botan_constant_time_compare(const uint8_t* x, const uint8_t* y, size_t len) {
328 if(len > 0 && any_null_pointers(x, y)) {
330 }
331 auto same = Botan::CT::is_equal(x, y, len);
332 // Return 0 if same or -1 otherwise
333 return static_cast<int>(same.select(1, 0)) - 1;
334}
335
336int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len) {
337 return botan_constant_time_compare(x, y, len);
338}
339
340int botan_scrub_mem(void* mem, size_t bytes) {
341 if(bytes > 0 && mem == nullptr) {
343 }
344 Botan::secure_scrub_memory(mem, bytes);
345 return BOTAN_FFI_SUCCESS;
346}
347
348int botan_hex_encode(const uint8_t* in, size_t len, char* out, uint32_t flags) {
349 if(len > 0 && (in == nullptr || out == nullptr)) {
351 }
352 return ffi_guard_thunk(__func__, [=]() -> int {
353 const bool uppercase = (flags & BOTAN_FFI_HEX_LOWER_CASE) == 0;
354 Botan::hex_encode(out, in, len, uppercase);
355 return BOTAN_FFI_SUCCESS;
356 });
357}
358
359int botan_hex_decode(const char* hex_str, size_t in_len, uint8_t* out, size_t* out_len) {
360 if(any_null_pointers(hex_str, out_len)) {
362 }
363 return ffi_guard_thunk(__func__, [=]() -> int {
364 const std::vector<uint8_t> bin = Botan::hex_decode(hex_str, in_len);
365 return Botan_FFI::write_vec_output(out, out_len, bin);
366 });
367}
368
369int botan_base64_encode(const uint8_t* in, size_t len, char* out, size_t* out_len) {
370 if(len > 0 && in == nullptr) {
372 }
373 return ffi_guard_thunk(__func__, [=]() -> int {
374 const std::string base64 = Botan::base64_encode(in, len);
375 return Botan_FFI::write_str_output(out, out_len, base64);
376 });
377}
378
379int botan_base64_decode(const char* base64_str, size_t in_len, uint8_t* out, size_t* out_len) {
380 if(any_null_pointers(out, out_len, base64_str)) {
382 }
383
384 return ffi_guard_thunk(__func__, [=]() -> int {
385 if(*out_len < Botan::base64_decode_max_output(in_len)) {
386 *out_len = Botan::base64_decode_max_output(in_len);
388 }
389
390 *out_len = Botan::base64_decode(out, std::string(base64_str, in_len));
391 return BOTAN_FFI_SUCCESS;
392 });
393}
394}
uint32_t botan_version_datestamp()
Definition ffi.cpp:323
int botan_same_mem(const uint8_t *x, const uint8_t *y, size_t len)
Definition ffi.cpp:336
const char * botan_version_string()
Definition ffi.cpp:307
int botan_base64_decode(const char *base64_str, size_t in_len, uint8_t *out, size_t *out_len)
Definition ffi.cpp:379
uint32_t botan_version_patch()
Definition ffi.cpp:319
int botan_base64_encode(const uint8_t *in, size_t len, char *out, size_t *out_len)
Definition ffi.cpp:369
int botan_scrub_mem(void *mem, size_t bytes)
Definition ffi.cpp:340
int botan_hex_encode(const uint8_t *in, size_t len, char *out, uint32_t flags)
Definition ffi.cpp:348
uint32_t botan_version_major()
Definition ffi.cpp:311
uint32_t botan_ffi_api_version()
Definition ffi.cpp:223
int botan_ffi_supports_api(uint32_t api_version)
Definition ffi.cpp:227
const char * botan_error_description(int err)
Definition ffi.cpp:146
uint32_t botan_version_minor()
Definition ffi.cpp:315
int botan_constant_time_compare(const uint8_t *x, const uint8_t *y, size_t len)
Definition ffi.cpp:327
int botan_hex_decode(const char *hex_str, size_t in_len, uint8_t *out, size_t *out_len)
Definition ffi.cpp:359
const char * botan_error_last_exception_message()
Definition ffi.cpp:142
#define BOTAN_FFI_HEX_LOWER_CASE
Definition ffi.h:247
void * botan_view_ctx
Definition ffi.h:152
@ BOTAN_FFI_ERROR_TPM_ERROR
Definition ffi.h:144
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:138
@ BOTAN_FFI_ERROR_INVALID_KEY_LENGTH
Definition ffi.h:134
@ BOTAN_FFI_ERROR_KEY_NOT_SET
Definition ffi.h:133
@ BOTAN_FFI_ERROR_TLS_ERROR
Definition ffi.h:141
@ BOTAN_FFI_ERROR_EXCEPTION_THROWN
Definition ffi.h:125
@ BOTAN_FFI_ERROR_OUT_OF_MEMORY
Definition ffi.h:126
@ BOTAN_FFI_ERROR_OUT_OF_RANGE
Definition ffi.h:136
@ BOTAN_FFI_ERROR_INTERNAL_ERROR
Definition ffi.h:128
@ BOTAN_FFI_INVALID_VERIFIER
Definition ffi.h:116
@ BOTAN_FFI_ERROR_INVALID_OBJECT
Definition ffi.h:139
@ BOTAN_FFI_ERROR_UNKNOWN_ERROR
Definition ffi.h:146
@ BOTAN_FFI_ERROR_HTTP_ERROR
Definition ffi.h:142
@ BOTAN_FFI_ERROR_BAD_FLAG
Definition ffi.h:130
@ BOTAN_FFI_ERROR_INVALID_INPUT
Definition ffi.h:118
@ BOTAN_FFI_ERROR_STRING_CONVERSION_ERROR
Definition ffi.h:123
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:131
@ BOTAN_FFI_SUCCESS
Definition ffi.h:114
@ BOTAN_FFI_ERROR_SYSTEM_ERROR
Definition ffi.h:127
@ BOTAN_FFI_ERROR_ROUGHTIME_ERROR
Definition ffi.h:143
@ BOTAN_FFI_ERROR_NO_VALUE
Definition ffi.h:120
@ BOTAN_FFI_ERROR_INVALID_OBJECT_STATE
Definition ffi.h:135
@ BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE
Definition ffi.h:122
@ BOTAN_FFI_ERROR_BAD_MAC
Definition ffi.h:119
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition ffi.h:132
#define BOTAN_HAS_FFI
Definition build.h:202
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
Definition ct_utils.h:798
bool read_env_variable(std::string &value_out, std::string_view var_name)
Definition os_utils.cpp:449
void ffi_clear_last_exception()
Definition ffi.cpp:85
int ffi_error_exception_thrown(const char *func_name, const char *exn, int rc)
Definition ffi.cpp:89
int botan_view_bin_bounce_fn(botan_view_ctx vctx, const uint8_t *buf, size_t len)
Definition ffi.cpp:111
int botan_view_str_bounce_fn(botan_view_ctx vctx, const char *str, size_t len)
Definition ffi.cpp:107
int ffi_guard_thunk(const char *func_name, T thunk)
Definition ffi_util.h:95
int write_vec_output(uint8_t out[], size_t *out_len, std::span< const uint8_t > buf)
Definition ffi_util.h:267
bool any_null_pointers(Ptrs... ptr)
Definition mem_utils.h:54
int write_str_output(char out[], size_t *out_len, const std::string &str)
Definition ffi_util.h:271
uint32_t version_minor()
Definition version.cpp:59
uint32_t version_major()
Definition version.cpp:55
const char * version_cstr()
Definition version.cpp:20
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition base64.cpp:161
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
uint32_t version_datestamp()
Definition version.cpp:32
void secure_scrub_memory(void *ptr, size_t n)
Definition mem_utils.cpp:25
uint32_t version_patch()
Definition version.cpp:63
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:169
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition hex.cpp:34
size_t base64_decode_max_output(size_t input_length)
Definition base64.cpp:201
size_t hex_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool ignore_ws)
Definition hex.cpp:75
ErrorType
Definition exceptn.h:21
constexpr void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:118