• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5134090420

31 May 2023 03:12PM UTC coverage: 91.721% (-0.3%) from 91.995%
5134090420

push

github

randombit
Merge GH #3565 Disable noisy/pointless pylint warnings

76048 of 82912 relevant lines covered (91.72%)

11755290.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.31
/src/lib/ffi/ffi.cpp
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/ffi_util.h>
14
#include <botan/internal/os_utils.h>
15
#include <cstdio>
16
#include <cstdlib>
17

18
namespace Botan_FFI {
19

20
thread_local std::string g_last_exception_what;
94,466✔
21

22
int ffi_error_exception_thrown(const char* func_name, const char* exn, int rc) {
13✔
23
   g_last_exception_what.assign(exn);
13✔
24

25
   std::string val;
13✔
26
   if(Botan::OS::read_env_variable(val, "BOTAN_FFI_PRINT_EXCEPTIONS") == true && !val.empty()) {
13✔
27
      static_cast<void>(std::fprintf(stderr, "in %s exception '%s' returning %d\n", func_name, exn, rc));
×
28
   }
29
   return rc;
13✔
30
}
13✔
31

32
int botan_view_str_bounce_fn(botan_view_ctx vctx, const char* str, size_t len) {
68✔
33
   return botan_view_bin_bounce_fn(vctx, reinterpret_cast<const uint8_t*>(str), len);
68✔
34
}
35

36
int botan_view_bin_bounce_fn(botan_view_ctx vctx, const uint8_t* buf, size_t len) {
155✔
37
   if(vctx == nullptr || buf == nullptr) {
155✔
38
      return BOTAN_FFI_ERROR_NULL_POINTER;
39
   }
40

41
   botan_view_bounce_struct* ctx = static_cast<botan_view_bounce_struct*>(vctx);
155✔
42

43
   const size_t avail = *ctx->out_len;
155✔
44
   *ctx->out_len = len;
155✔
45

46
   if(avail < len || ctx->out_ptr == nullptr) {
155✔
47
      if(ctx->out_ptr) {
72✔
48
         Botan::clear_mem(ctx->out_ptr, avail);
×
49
      }
50
      return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
72✔
51
   } else {
52
      Botan::copy_mem(ctx->out_ptr, buf, len);
83✔
53
      return BOTAN_FFI_SUCCESS;
83✔
54
   }
55
}
56

57
namespace {
58

59
int ffi_map_error_type(Botan::ErrorType err) {
7✔
60
   switch(err) {
7✔
61
      case Botan::ErrorType::Unknown:
62
         return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
63

64
      case Botan::ErrorType::SystemError:
×
65
      case Botan::ErrorType::IoError:
×
66
      case Botan::ErrorType::Pkcs11Error:
×
67
      case Botan::ErrorType::CommonCryptoError:
×
68
      case Botan::ErrorType::TPMError:
×
69
      case Botan::ErrorType::ZlibError:
×
70
      case Botan::ErrorType::Bzip2Error:
×
71
      case Botan::ErrorType::LzmaError:
×
72
      case Botan::ErrorType::DatabaseError:
×
73
         return BOTAN_FFI_ERROR_SYSTEM_ERROR;
×
74

75
      case Botan::ErrorType::NotImplemented:
×
76
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
77
      case Botan::ErrorType::OutOfMemory:
×
78
         return BOTAN_FFI_ERROR_OUT_OF_MEMORY;
×
79
      case Botan::ErrorType::InternalError:
×
80
         return BOTAN_FFI_ERROR_INTERNAL_ERROR;
×
81
      case Botan::ErrorType::InvalidObjectState:
2✔
82
         return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
2✔
83
      case Botan::ErrorType::KeyNotSet:
2✔
84
         return BOTAN_FFI_ERROR_KEY_NOT_SET;
2✔
85
      case Botan::ErrorType::InvalidArgument:
2✔
86
      case Botan::ErrorType::InvalidNonceLength:
2✔
87
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
2✔
88

89
      case Botan::ErrorType::EncodingFailure:
1✔
90
      case Botan::ErrorType::DecodingFailure:
1✔
91
         return BOTAN_FFI_ERROR_INVALID_INPUT;
1✔
92

93
      case Botan::ErrorType::InvalidTag:
×
94
         return BOTAN_FFI_ERROR_BAD_MAC;
×
95

96
      case Botan::ErrorType::InvalidKeyLength:
×
97
         return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
×
98
      case Botan::ErrorType::LookupError:
×
99
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
100

101
      case Botan::ErrorType::HttpError:
×
102
         return BOTAN_FFI_ERROR_HTTP_ERROR;
×
103
      case Botan::ErrorType::TLSError:
×
104
         return BOTAN_FFI_ERROR_TLS_ERROR;
×
105
      case Botan::ErrorType::RoughtimeError:
×
106
         return BOTAN_FFI_ERROR_ROUGHTIME_ERROR;
×
107
   }
108

109
   return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
110
}
111

112
}  // namespace
113

114
int ffi_guard_thunk(const char* func_name, const std::function<int()>& thunk) {
94,451✔
115
   g_last_exception_what.clear();
94,451✔
116

117
   try {
94,451✔
118
      return thunk();
188,902✔
119
   } catch(std::bad_alloc&) {
13✔
120
      return ffi_error_exception_thrown(func_name, "bad_alloc", BOTAN_FFI_ERROR_OUT_OF_MEMORY);
×
121
   } catch(Botan_FFI::FFI_Error& e) {
6✔
122
      return ffi_error_exception_thrown(func_name, e.what(), e.error_code());
6✔
123
   } catch(Botan::Exception& e) {
13✔
124
      return ffi_error_exception_thrown(func_name, e.what(), ffi_map_error_type(e.error_type()));
7✔
125
   } catch(std::exception& e) {
7✔
126
      return ffi_error_exception_thrown(func_name, e.what());
×
127
   } catch(...) {
×
128
      return ffi_error_exception_thrown(func_name, "unknown exception");
×
129
   }
×
130

131
   return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
132
}
133

134
}  // namespace Botan_FFI
135

136
extern "C" {
137

138
using namespace Botan_FFI;
139

140
const char* botan_error_last_exception_message() { return g_last_exception_what.c_str(); }
2✔
141

142
const char* botan_error_description(int err) {
152✔
143
   switch(err) {
152✔
144
      case BOTAN_FFI_SUCCESS:
145
         return "OK";
146

147
      case BOTAN_FFI_INVALID_VERIFIER:
1✔
148
         return "Invalid verifier";
1✔
149

150
      case BOTAN_FFI_ERROR_INVALID_INPUT:
2✔
151
         return "Invalid input";
2✔
152

153
      case BOTAN_FFI_ERROR_BAD_MAC:
1✔
154
         return "Invalid authentication code";
1✔
155

156
      case BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE:
1✔
157
         return "Insufficient buffer space";
1✔
158

159
      case BOTAN_FFI_ERROR_STRING_CONVERSION_ERROR:
1✔
160
         return "String conversion error";
1✔
161

162
      case BOTAN_FFI_ERROR_EXCEPTION_THROWN:
1✔
163
         return "Exception thrown";
1✔
164

165
      case BOTAN_FFI_ERROR_OUT_OF_MEMORY:
1✔
166
         return "Out of memory";
1✔
167

168
      case BOTAN_FFI_ERROR_SYSTEM_ERROR:
1✔
169
         return "Error while calling system API";
1✔
170

171
      case BOTAN_FFI_ERROR_INTERNAL_ERROR:
1✔
172
         return "Internal error";
1✔
173

174
      case BOTAN_FFI_ERROR_BAD_FLAG:
1✔
175
         return "Bad flag";
1✔
176

177
      case BOTAN_FFI_ERROR_NULL_POINTER:
1✔
178
         return "Null pointer argument";
1✔
179

180
      case BOTAN_FFI_ERROR_BAD_PARAMETER:
1✔
181
         return "Bad parameter";
1✔
182

183
      case BOTAN_FFI_ERROR_KEY_NOT_SET:
1✔
184
         return "Key not set on object";
1✔
185

186
      case BOTAN_FFI_ERROR_INVALID_KEY_LENGTH:
1✔
187
         return "Invalid key length";
1✔
188

189
      case BOTAN_FFI_ERROR_INVALID_OBJECT_STATE:
1✔
190
         return "Invalid object state";
1✔
191

192
      case BOTAN_FFI_ERROR_NOT_IMPLEMENTED:
2✔
193
         return "Not implemented";
2✔
194

195
      case BOTAN_FFI_ERROR_INVALID_OBJECT:
1✔
196
         return "Invalid object handle";
1✔
197

198
      case BOTAN_FFI_ERROR_TLS_ERROR:
1✔
199
         return "TLS error";
1✔
200

201
      case BOTAN_FFI_ERROR_HTTP_ERROR:
1✔
202
         return "HTTP error";
1✔
203

204
      case BOTAN_FFI_ERROR_UNKNOWN_ERROR:
1✔
205
         return "Unknown error";
1✔
206

207
      default:
129✔
208
         return "Unknown error";
129✔
209
   }
210
}
211

212
/*
213
* Versioning
214
*/
215
uint32_t botan_ffi_api_version() { return BOTAN_HAS_FFI; }
3✔
216

217
int botan_ffi_supports_api(uint32_t api_version) {
7✔
218
   // This is the API introduced in 3.0
219
   if(api_version == 20230403) {
7✔
220
      return BOTAN_FFI_SUCCESS;
221
   }
222

223
   // This is the API introduced in 2.18
224
   if(api_version == 20210220) {
5✔
225
      return BOTAN_FFI_SUCCESS;
226
   }
227

228
   // This is the API introduced in 2.13
229
   if(api_version == 20191214) {
5✔
230
      return BOTAN_FFI_SUCCESS;
231
   }
232

233
   // This is the API introduced in 2.8
234
   if(api_version == 20180713) {
5✔
235
      return BOTAN_FFI_SUCCESS;
236
   }
237

238
   // This is the API introduced in 2.3
239
   if(api_version == 20170815) {
4✔
240
      return BOTAN_FFI_SUCCESS;
241
   }
242

243
   // This is the API introduced in 2.1
244
   if(api_version == 20170327) {
3✔
245
      return BOTAN_FFI_SUCCESS;
246
   }
247

248
   // This is the API introduced in 2.0
249
   if(api_version == 20150515) {
2✔
250
      return BOTAN_FFI_SUCCESS;
1✔
251
   }
252

253
   // Something else:
254
   return -1;
255
}
256

257
const char* botan_version_string() { return Botan::version_cstr(); }
2✔
258

259
uint32_t botan_version_major() { return Botan::version_major(); }
2✔
260

261
uint32_t botan_version_minor() { return Botan::version_minor(); }
2✔
262

263
uint32_t botan_version_patch() { return Botan::version_patch(); }
1✔
264

265
uint32_t botan_version_datestamp() { return Botan::version_datestamp(); }
1✔
266

267
int botan_constant_time_compare(const uint8_t* x, const uint8_t* y, size_t len) {
28✔
268
   return Botan::constant_time_compare(x, y, len) ? 0 : -1;
28✔
269
}
270

271
int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len) { return botan_constant_time_compare(x, y, len); }
×
272

273
int botan_scrub_mem(void* mem, size_t bytes) {
1✔
274
   Botan::secure_scrub_memory(mem, bytes);
1✔
275
   return BOTAN_FFI_SUCCESS;
1✔
276
}
277

278
int botan_hex_encode(const uint8_t* in, size_t len, char* out, uint32_t flags) {
3✔
279
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
280
      const bool uppercase = (flags & BOTAN_FFI_HEX_LOWER_CASE) == 0;
3✔
281
      Botan::hex_encode(out, in, len, uppercase);
3✔
282
      return BOTAN_FFI_SUCCESS;
3✔
283
   });
3✔
284
}
285

286
int botan_hex_decode(const char* hex_str, size_t in_len, uint8_t* out, size_t* out_len) {
2✔
287
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
288
      const std::vector<uint8_t> bin = Botan::hex_decode(hex_str, in_len);
2✔
289
      return Botan_FFI::write_vec_output(out, out_len, bin);
2✔
290
   });
4✔
291
}
292

293
int botan_base64_encode(const uint8_t* in, size_t len, char* out, size_t* out_len) {
2✔
294
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
295
      const std::string base64 = Botan::base64_encode(in, len);
2✔
296
      return Botan_FFI::write_str_output(out, out_len, base64);
2✔
297
   });
4✔
298
}
299

300
int botan_base64_decode(const char* base64_str, size_t in_len, uint8_t* out, size_t* out_len) {
2✔
301
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
302
      if(*out_len < Botan::base64_decode_max_output(in_len)) {
2✔
303
         *out_len = Botan::base64_decode_max_output(in_len);
1✔
304
         return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
1✔
305
      }
306

307
      *out_len = Botan::base64_decode(out, std::string(base64_str, in_len));
1✔
308
      return BOTAN_FFI_SUCCESS;
1✔
309
   });
2✔
310
}
311
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc