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