Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
19 class BOTAN_UNSTABLE_API FFI_Error final : public Botan::Exception
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 noexcept override { return m_err_code; }
28
29 Botan::ErrorType error_type() const noexcept override { return Botan::ErrorType::InvalidArgument; }
30
31 private:
32 int m_err_code;
33 };
34
35 template<typename T, uint32_t MAGIC>
36 struct botan_struct
37 {
38 public:
39 botan_struct(T* obj) : m_magic(MAGIC), m_obj(obj) {}
40 virtual ~botan_struct() { m_magic = 0; m_obj.reset(); }
41
42 bool magic_ok() const { return (m_magic == MAGIC); }
43
44 T* unsafe_get() const
45 {
46 return m_obj.get();
47 }
48 private:
49 uint32_t m_magic = 0;
50 std::unique_ptr<T> m_obj;
51 };
52
53 #define BOTAN_FFI_DECLARE_STRUCT(NAME, TYPE, MAGIC) \
54 struct NAME final : public Botan_FFI::botan_struct<TYPE, MAGIC> { explicit NAME(TYPE* x) : botan_struct(x) {} }
55
56 // Declared in ffi.cpp
57 int ffi_error_exception_thrown(const char* func_name, const char* exn,
58 int rc = BOTAN_FFI_ERROR_EXCEPTION_THROWN);
59
60 template<typename T, uint32_t M>
61 T& safe_get(botan_struct<T,M>* p)
62 {
63 if(!p)
64 throw FFI_Error("Null pointer argument", BOTAN_FFI_ERROR_NULL_POINTER);
65 if(p->magic_ok() == false)
66 throw FFI_Error("Bad magic in ffi object", BOTAN_FFI_ERROR_INVALID_OBJECT);
67
68 if(T* t = p->unsafe_get())
69 return *t;
70
71 throw FFI_Error("Invalid object pointer", BOTAN_FFI_ERROR_INVALID_OBJECT);
72 }
73
74 int ffi_guard_thunk(const char* func_name, std::function<int ()>);
75
76 template<typename T, uint32_t M, typename F>
77 int apply_fn(botan_struct<T, M>* o, const char* func_name, F func)
78 {
79 if(!o)
80 return BOTAN_FFI_ERROR_NULL_POINTER;
81
82 if(o->magic_ok() == false)
83 return BOTAN_FFI_ERROR_INVALID_OBJECT;
84
85 T* p = o->unsafe_get();
86 if(p == nullptr)
87 return BOTAN_FFI_ERROR_INVALID_OBJECT;
88
89 return ffi_guard_thunk(func_name, [&]() { return func(*p); });
90 }
91
92 #define BOTAN_FFI_DO(T, obj, param, block) \
93 apply_fn(obj, __func__, \
94 [=](T& param) -> int { do { block } while(0); return BOTAN_FFI_SUCCESS; })
95
96 /*
97 * Like BOTAN_FFI_DO but with no trailing return with the expectation
98 * that the block always returns a value. This exists because otherwise
99 * MSVC warns about the dead return after the block in FFI_DO.
100 */
101 #define BOTAN_FFI_RETURNING(T, obj, param, block) \
102 apply_fn(obj, __func__, \
103 [=](T& param) -> int { do { block } while(0); })
104
105 template<typename T, uint32_t M>
106 int ffi_delete_object(botan_struct<T, M>* obj, const char* func_name)
107 {
108 try
109 {
110 if(obj == nullptr)
111 return BOTAN_FFI_SUCCESS; // ignore delete of null objects
112
113 if(obj->magic_ok() == false)
114 return BOTAN_FFI_ERROR_INVALID_OBJECT;
115
116 delete obj;
117 return BOTAN_FFI_SUCCESS;
118 }
119 catch(std::exception& e)
120 {
121 return ffi_error_exception_thrown(func_name, e.what());
122 }
123 catch(...)
124 {
125 return ffi_error_exception_thrown(func_name, "unknown exception");
126 }
127 }
128
129 #define BOTAN_FFI_CHECKED_DELETE(o) ffi_delete_object(o, __func__)
130
131 inline int write_output(uint8_t out[], size_t* out_len, const uint8_t buf[], size_t buf_len)
132 {
133 if(out_len == nullptr)
134 return BOTAN_FFI_ERROR_NULL_POINTER;
135
136 const size_t avail = *out_len;
137 *out_len = buf_len;
138
139 if((avail >= buf_len) && (out != nullptr))
140 {
141 Botan::copy_mem(out, buf, buf_len);
142 return BOTAN_FFI_SUCCESS;
143 }
144 else
145 {
146 if(out != nullptr)
147 {
148 Botan::clear_mem(out, avail);
149 }
150 return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
151 }
152 }
153
154 template<typename Alloc>
155 int write_vec_output(uint8_t out[], size_t* out_len, const std::vector<uint8_t, Alloc>& buf)
156 {
157 return write_output(out, out_len, buf.data(), buf.size());
158 }
159
160 inline int write_str_output(uint8_t out[], size_t* out_len, const std::string& str)
161 {
162 return write_output(out, out_len,
163 Botan::cast_char_ptr_to_uint8(str.data()),
164 str.size() + 1);
165 }
166
167 inline int write_str_output(char out[], size_t* out_len, const std::string& str)
168 {
169 return write_str_output(Botan::cast_char_ptr_to_uint8(out), out_len, str);
170 }
171
172 inline int write_str_output(char out[], size_t* out_len, const std::vector<uint8_t>& str_vec)
173 {
174 return write_output(Botan::cast_char_ptr_to_uint8(out),
175 out_len,
176 str_vec.data(),
177 str_vec.size());
178 }
179
180 }
181
182 #endif
Botan_FFI::ffi_guard_thunk
int ffi_guard_thunk(const char *func_name, std::function< int()> thunk)
Definition: ffi.cpp:89
BOTAN_UNSTABLE_API
#define BOTAN_UNSTABLE_API
Definition: compiler.h:38
Botan_FFI::botan_struct::~botan_struct
virtual ~botan_struct()
Definition: ffi_util.h:40
Botan_FFI::FFI_Error::error_type
Botan::ErrorType error_type() const noexceptoverride
Definition: ffi_util.h:29
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_Error::FFI_Error
FFI_Error(const std::string &what, int err_code)
Definition: ffi_util.h:22
Botan::Exception
Definition: exceptn.h:85
Botan::clear_mem
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:112
Botan_FFI::botan_struct
Definition: ffi_util.h:36
final
int(* final)(unsigned char *, CTX *)
Definition: commoncrypto_hash.cpp:28
Botan::cast_char_ptr_to_uint8
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition: mem_ops.h:189
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_FFI::botan_struct::unsafe_get
T * unsafe_get() const
Definition: ffi_util.h:44
BOTAN_FFI_ERROR_EXCEPTION_THROWN
Definition: ffi.h:70
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::ErrorType::InvalidArgument
BOTAN_FFI_ERROR_NULL_POINTER
Definition: ffi.h:76
Botan::ErrorType
ErrorType
Definition: exceptn.h:20
Botan_FFI::FFI_Error::error_code
int error_code() const noexceptoverride
Definition: ffi_util.h:27
BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE
Definition: ffi.h:68
Botan_FFI
Definition: ffi.cpp:17
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:132
Botan_FFI::apply_fn
int apply_fn(botan_struct< T, M > *o, const char *func_name, F func)
Definition: ffi_util.h:77
Botan_FFI::safe_get
T & safe_get(botan_struct< T, M > *p)
Definition: ffi_util.h:61
Botan_FFI::ffi_delete_object
int ffi_delete_object(botan_struct< T, M > *obj, const char *func_name)
Definition: ffi_util.h:106
Botan_FFI::botan_struct::magic_ok
bool magic_ok() const
Definition: ffi_util.h:42
Botan_FFI::FFI_Error
Definition: ffi_util.h:19
T
fe T
Definition: ge.cpp:37
Botan_FFI::botan_struct::botan_struct
botan_struct(T *obj)
Definition: ffi_util.h:39
BOTAN_FFI_SUCCESS
Definition: ffi.h:62
Botan_FFI::write_output
int write_output(uint8_t out[], size_t *out_len, const uint8_t buf[], size_t buf_len)
Definition: ffi_util.h:131
BOTAN_FFI_ERROR_INVALID_OBJECT
Definition: ffi.h:83