Botan 3.0.0-alpha0
Crypto and TLS for C&
ffi_cipher.cpp
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#include <botan/ffi.h>
8#include <botan/internal/ffi_util.h>
9#include <botan/aead.h>
10
11extern "C" {
12
13using namespace Botan_FFI;
14
15struct botan_cipher_struct final : public botan_struct<Botan::Cipher_Mode, 0xB4A2BF9C>
16 {
17 explicit botan_cipher_struct(std::unique_ptr<Botan::Cipher_Mode> x) :
18 botan_struct(std::move(x)) {}
20 };
21
22int botan_cipher_init(botan_cipher_t* cipher, const char* cipher_name, uint32_t flags)
23 {
24 return ffi_guard_thunk(__func__, [=]() -> int {
27 std::unique_ptr<Botan::Cipher_Mode> mode(Botan::Cipher_Mode::create(cipher_name, dir));
28 if(!mode)
30 *cipher = new botan_cipher_struct(std::move(mode));
31 return BOTAN_FFI_SUCCESS;
32 });
33 }
34
36 {
37 return BOTAN_FFI_CHECKED_DELETE(cipher);
38 }
39
41 {
42 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { c.clear(); });
43 }
44
46 {
47 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { c.reset(); });
48 }
49
50int botan_cipher_output_length(botan_cipher_t cipher, size_t in_len, size_t* out_len)
51 {
52 if(out_len == nullptr)
54
55 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *out_len = c.output_length(in_len); });
56 }
57
59 size_t* out_minimum_keylength,
60 size_t* out_maximum_keylength)
61 {
62 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, {
63 *out_minimum_keylength = c.key_spec().minimum_keylength();
64 *out_maximum_keylength = c.key_spec().maximum_keylength();
65 });
66 }
67
69 size_t* out_minimum_keylength,
70 size_t* out_maximum_keylength,
71 size_t* out_keylength_modulo)
72 {
73 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, {
74 if(out_minimum_keylength)
75 *out_minimum_keylength = c.key_spec().minimum_keylength();
76 if(out_maximum_keylength)
77 *out_maximum_keylength = c.key_spec().maximum_keylength();
78 if(out_keylength_modulo)
79 *out_keylength_modulo = c.key_spec().keylength_multiple();
80 });
81 }
82
84 const uint8_t* key, size_t key_len)
85 {
86 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { c.set_key(key, key_len); });
87 }
88
90 const uint8_t* nonce, size_t nonce_len)
91 {
92 return ffi_guard_thunk(__func__, [=]() -> int {
93 Botan::Cipher_Mode& cipher = safe_get(cipher_obj);
94 cipher.start(nonce, nonce_len);
95 cipher_obj->m_buf.reserve(cipher.update_granularity());
96 return BOTAN_FFI_SUCCESS;
97 });
98 }
99
101 uint32_t flags,
102 uint8_t output_ptr[],
103 size_t orig_output_size,
104 size_t* output_written,
105 const uint8_t input_ptr[],
106 size_t orig_input_size,
107 size_t* input_consumed)
108 {
109 return ffi_guard_thunk(__func__, [=]() -> int {
110
111 size_t input_size = orig_input_size;
112 size_t output_size = orig_output_size;
113 const uint8_t* input = input_ptr;
114 uint8_t* output = output_ptr;
115
116 using namespace Botan;
117 Cipher_Mode& cipher = safe_get(cipher_obj);
118 secure_vector<uint8_t>& mbuf = cipher_obj->m_buf;
119
120 const bool final_input = (flags & BOTAN_CIPHER_UPDATE_FLAG_FINAL);
121
122 if(final_input)
123 {
124 mbuf.assign(input, input + input_size);
125 *input_consumed = input_size;
126 *output_written = 0;
127
128 try
129 {
130 cipher.finish(mbuf);
131 }
133 {
135 }
136
137 *output_written = mbuf.size();
138
139 if(mbuf.size() <= output_size)
140 {
141 copy_mem(output, mbuf.data(), mbuf.size());
142 mbuf.clear();
143 return BOTAN_FFI_SUCCESS;
144 }
145
146 return -1;
147 }
148
149 if(input_size == 0)
150 {
151 // Currently must take entire buffer in this case
152 *output_written = mbuf.size();
153 if(output_size >= mbuf.size())
154 {
155 copy_mem(output, mbuf.data(), mbuf.size());
156 mbuf.clear();
157 return BOTAN_FFI_SUCCESS;
158 }
159
160 return -1;
161 }
162
163 const size_t ud = cipher.update_granularity();
164 BOTAN_ASSERT(cipher.update_granularity() > cipher.minimum_final_size(), "logic error");
165
166 mbuf.resize(ud);
167 size_t taken = 0, written = 0;
168
169 while(input_size >= ud && output_size >= ud)
170 {
171 // FIXME we can use process here and avoid the copy
172 copy_mem(mbuf.data(), input, ud);
173 cipher.update(mbuf);
174
175 input_size -= ud;
176 copy_mem(output, mbuf.data(), ud);
177 input += ud;
178 taken += ud;
179
180 output_size -= ud;
181 output += ud;
182 written += ud;
183 }
184
185 *output_written = written;
186 *input_consumed = taken;
187
188 return BOTAN_FFI_SUCCESS;
189 });
190 }
191
193 const uint8_t* ad,
194 size_t ad_len)
195 {
196 return BOTAN_FFI_RETURNING(Botan::Cipher_Mode, cipher, c, {
197 if(Botan::AEAD_Mode* aead = dynamic_cast<Botan::AEAD_Mode*>(&c))
198 {
199 aead->set_associated_data(ad, ad_len);
200 return BOTAN_FFI_SUCCESS;
201 }
203 });
204 }
205
207 {
208 return BOTAN_FFI_RETURNING(Botan::Cipher_Mode, cipher, c, {
209 return c.valid_nonce_length(nl) ? 1 : 0;
210 });
211 }
212
214 {
215 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *nl = c.default_nonce_length(); });
216 }
217
219 {
220 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *ug = c.update_granularity(); });
221 }
222
224 {
225 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *tl = c.tag_size(); });
226 }
227
228int botan_cipher_name(botan_cipher_t cipher, char* name, size_t* name_len)
229 {
230 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, {
231 return write_str_output(name, name_len, c.name()); });
232 }
233
234}
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:54
static std::unique_ptr< Cipher_Mode > create(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
Definition: cipher_mode.cpp:50
virtual size_t default_nonce_length() const =0
virtual void reset()=0
void start(const std::vector< uint8_t, Alloc > &nonce)
Definition: cipher_mode.h:69
virtual size_t output_length(size_t input_length) const =0
virtual void finish(secure_vector< uint8_t > &final_block, size_t offset=0)=0
virtual size_t tag_size() const
Definition: cipher_mode.h:174
void update(secure_vector< uint8_t > &buffer, size_t offset=0)
Definition: cipher_mode.h:112
virtual size_t minimum_final_size() const =0
virtual size_t update_granularity() const =0
virtual bool valid_nonce_length(size_t nonce_len) const =0
size_t minimum_keylength() const
Definition: sym_algo.h:62
void set_key(const SymmetricKey &key)
Definition: sym_algo.h:147
virtual void clear()=0
virtual Key_Length_Specification key_spec() const =0
std::string name
int(* final)(unsigned char *, CTX *)
#define BOTAN_CIPHER_INIT_FLAG_ENCRYPT
Definition: ffi.h:450
#define BOTAN_CIPHER_UPDATE_FLAG_FINAL
Definition: ffi.h:532
#define BOTAN_CIPHER_INIT_FLAG_MASK_DIRECTION
Definition: ffi.h:449
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition: ffi.h:83
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition: ffi.h:77
@ BOTAN_FFI_SUCCESS
Definition: ffi.h:63
@ BOTAN_FFI_ERROR_BAD_MAC
Definition: ffi.h:67
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition: ffi.h:78
struct botan_cipher_struct * botan_cipher_t
Definition: ffi.h:447
int botan_cipher_update(botan_cipher_t cipher_obj, uint32_t flags, uint8_t output_ptr[], size_t orig_output_size, size_t *output_written, const uint8_t input_ptr[], size_t orig_input_size, size_t *input_consumed)
Definition: ffi_cipher.cpp:100
int botan_cipher_valid_nonce_length(botan_cipher_t cipher, size_t nl)
Definition: ffi_cipher.cpp:206
int botan_cipher_output_length(botan_cipher_t cipher, size_t in_len, size_t *out_len)
Definition: ffi_cipher.cpp:50
int botan_cipher_reset(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:45
int botan_cipher_destroy(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:35
int botan_cipher_name(botan_cipher_t cipher, char *name, size_t *name_len)
Definition: ffi_cipher.cpp:228
int botan_cipher_set_associated_data(botan_cipher_t cipher, const uint8_t *ad, size_t ad_len)
Definition: ffi_cipher.cpp:192
int botan_cipher_start(botan_cipher_t cipher_obj, const uint8_t *nonce, size_t nonce_len)
Definition: ffi_cipher.cpp:89
int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t *tl)
Definition: ffi_cipher.cpp:223
int botan_cipher_get_keyspec(botan_cipher_t cipher, size_t *out_minimum_keylength, size_t *out_maximum_keylength, size_t *out_keylength_modulo)
Definition: ffi_cipher.cpp:68
int botan_cipher_set_key(botan_cipher_t cipher, const uint8_t *key, size_t key_len)
Definition: ffi_cipher.cpp:83
int botan_cipher_clear(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:40
int botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t *nl)
Definition: ffi_cipher.cpp:213
int botan_cipher_init(botan_cipher_t *cipher, const char *cipher_name, uint32_t flags)
Definition: ffi_cipher.cpp:22
int botan_cipher_query_keylen(botan_cipher_t cipher, size_t *out_minimum_keylength, size_t *out_maximum_keylength)
Definition: ffi_cipher.cpp:58
int botan_cipher_get_update_granularity(botan_cipher_t cipher, size_t *ug)
Definition: ffi_cipher.cpp:218
#define BOTAN_FFI_DO(T, obj, param, block)
Definition: ffi_util.h:96
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition: ffi_util.h:126
#define BOTAN_FFI_RETURNING(T, obj, param, block)
Definition: ffi_util.h:105
Flags flags(Flag flags)
Definition: p11.h:860
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
Definition: alg_id.cpp:13
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:126
Cipher_Dir
Definition: cipher_mode.h:23
@ DECRYPTION
Definition: cipher_mode.h:23
@ ENCRYPTION
Definition: cipher_mode.h:23
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
Definition: bigint.h:1077