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