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