Botan  2.8.0
Crypto and TLS for C++11
ffi_util.h
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 #ifndef BOTAN_FFI_UTILS_H_
8 #define BOTAN_FFI_UTILS_H_
9 
10 #include <cstdint>
11 #include <memory>
12 #include <stdexcept>
13 #include <functional>
14 #include <botan/exceptn.h>
15 #include <botan/mem_ops.h>
16 
17 namespace Botan_FFI {
18 
20  {
21  public:
22  FFI_Error(const std::string& what, int err_code) :
23  Exception("FFI error", what),
24  m_err_code(err_code)
25  {}
26 
27  int error_code() const { return m_err_code; }
28 
29  private:
30  int m_err_code;
31  };
32 
33 template<typename T, uint32_t MAGIC>
35  {
36  public:
37  botan_struct(T* obj) : m_magic(MAGIC), m_obj(obj) {}
38  virtual ~botan_struct() { m_magic = 0; m_obj.reset(); }
39 
40  bool magic_ok() const { return (m_magic == MAGIC); }
41 
42  T* unsafe_get() const
43  {
44  return m_obj.get();
45  }
46  private:
47  uint32_t m_magic = 0;
48  std::unique_ptr<T> m_obj;
49  };
50 
51 #define BOTAN_FFI_DECLARE_STRUCT(NAME, TYPE, MAGIC) \
52  struct NAME final : public Botan_FFI::botan_struct<TYPE, MAGIC> { explicit NAME(TYPE* x) : botan_struct(x) {} }
53 
54 // Declared in ffi.cpp
55 int ffi_error_exception_thrown(const char* func_name, const char* exn,
57 
58 template<typename T, uint32_t M>
60  {
61  if(!p)
62  throw FFI_Error("Null pointer argument", BOTAN_FFI_ERROR_NULL_POINTER);
63  if(p->magic_ok() == false)
64  throw FFI_Error("Bad magic in ffi object", BOTAN_FFI_ERROR_INVALID_OBJECT);
65 
66  if(T* t = p->unsafe_get())
67  return *t;
68 
69  throw FFI_Error("Invalid object pointer", BOTAN_FFI_ERROR_INVALID_OBJECT);
70  }
71 
72 int ffi_guard_thunk(const char* func_name, std::function<int ()>);
73 
74 template<typename T, uint32_t M, typename F>
75 int apply_fn(botan_struct<T, M>* o, const char* func_name, F func)
76  {
77  if(!o)
79 
80  if(o->magic_ok() == false)
82 
83  return ffi_guard_thunk(func_name, [&]() { return func(*o->unsafe_get()); });
84  }
85 
86 #define BOTAN_FFI_DO(T, obj, param, block) \
87  apply_fn(obj, BOTAN_CURRENT_FUNCTION, \
88  [=](T& param) -> int { do { block } while(0); return BOTAN_FFI_SUCCESS; })
89 
90 template<typename T, uint32_t M>
91 int ffi_delete_object(botan_struct<T, M>* obj, const char* func_name)
92  {
93  try
94  {
95  if(obj == nullptr)
96  return BOTAN_FFI_SUCCESS; // ignore delete of null objects
97 
98  if(obj->magic_ok() == false)
100 
101  delete obj;
102  return BOTAN_FFI_SUCCESS;
103  }
104  catch(std::exception& e)
105  {
106  return ffi_error_exception_thrown(func_name, e.what());
107  }
108  catch(...)
109  {
110  return ffi_error_exception_thrown(func_name, "unknown exception");
111  }
112  }
113 
114 #define BOTAN_FFI_CHECKED_DELETE(o) ffi_delete_object(o, BOTAN_CURRENT_FUNCTION)
115 
116 inline int write_output(uint8_t out[], size_t* out_len, const uint8_t buf[], size_t buf_len)
117  {
118  if(out_len == nullptr)
120 
121  const size_t avail = *out_len;
122  *out_len = buf_len;
123 
124  if((avail >= buf_len) && (out != nullptr))
125  {
126  Botan::copy_mem(out, buf, buf_len);
127  return BOTAN_FFI_SUCCESS;
128  }
129  else
130  {
131  if(out != nullptr)
132  {
133  Botan::clear_mem(out, avail);
134  }
136  }
137  }
138 
139 template<typename Alloc>
140 int write_vec_output(uint8_t out[], size_t* out_len, const std::vector<uint8_t, Alloc>& buf)
141  {
142  return write_output(out, out_len, buf.data(), buf.size());
143  }
144 
145 inline int write_str_output(uint8_t out[], size_t* out_len, const std::string& str)
146  {
147  return write_output(out, out_len,
148  Botan::cast_char_ptr_to_uint8(str.data()),
149  str.size() + 1);
150  }
151 
152 inline int write_str_output(char out[], size_t* out_len, const std::string& str)
153  {
154  return write_str_output(Botan::cast_char_ptr_to_uint8(out), out_len, str);
155  }
156 
157 inline int write_str_output(char out[], size_t* out_len, const std::vector<uint8_t>& str_vec)
158  {
160  out_len,
161  str_vec.data(),
162  str_vec.size());
163  }
164 
165 }
166 
167 #endif
int ffi_guard_thunk(const char *func_name, std::function< int()> thunk)
Definition: ffi.cpp:28
#define BOTAN_UNSTABLE_API
Definition: compiler.h:34
virtual ~botan_struct()
Definition: ffi_util.h:38
int ffi_error_exception_thrown(const char *func_name, const char *exn, int rc)
Definition: ffi.cpp:19
FFI_Error(const std::string &what, int err_code)
Definition: ffi_util.h:22
int error_code() const
Definition: ffi_util.h:27
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:97
int(* final)(unsigned char *, CTX *)
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition: mem_ops.h:131
int write_vec_output(uint8_t out[], size_t *out_len, const std::vector< uint8_t, Alloc > &buf)
Definition: ffi_util.h:140
int write_str_output(uint8_t out[], size_t *out_len, const std::string &str)
Definition: ffi_util.h:145
T * unsafe_get() const
Definition: ffi_util.h:42
bool magic_ok() const
Definition: ffi_util.h:40
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
int apply_fn(botan_struct< T, M > *o, const char *func_name, F func)
Definition: ffi_util.h:75
T & safe_get(botan_struct< T, M > *p)
Definition: ffi_util.h:59
int ffi_delete_object(botan_struct< T, M > *obj, const char *func_name)
Definition: ffi_util.h:91
fe T
Definition: ge.cpp:37
int write_output(uint8_t out[], size_t *out_len, const uint8_t buf[], size_t buf_len)
Definition: ffi_util.h:116