Botan 2.19.5 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
11 extern "C" {
12
13 using namespace Botan_FFI;
14
15 struct botan_cipher_struct final : public botan_struct<Botan::Cipher_Mode, 0xB4A2BF9C>
16 {
17 explicit botan_cipher_struct(Botan::Cipher_Mode* x) : botan_struct(x) {}
18 Botan::secure_vector<uint8_t> m_buf;
19 };
20
21 int botan_cipher_init(botan_cipher_t* cipher, const char* cipher_name, uint32_t flags)
22 {
23 return ffi_guard_thunk(__func__, [=]() -> int {
24 const bool encrypt_p = ((flags & BOTAN_CIPHER_INIT_FLAG_MASK_DIRECTION) == BOTAN_CIPHER_INIT_FLAG_ENCRYPT);
25 const Botan::Cipher_Dir dir = encrypt_p ? Botan::ENCRYPTION : Botan::DECRYPTION;
26 std::unique_ptr<Botan::Cipher_Mode> mode(Botan::Cipher_Mode::create(cipher_name, dir));
27 if(!mode)
28 return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
29 *cipher = new botan_cipher_struct(mode.release());
30 return BOTAN_FFI_SUCCESS;
31 });
32 }
33
34 int botan_cipher_destroy(botan_cipher_t cipher)
35 {
36 return BOTAN_FFI_CHECKED_DELETE(cipher);
37 }
38
39 int botan_cipher_clear(botan_cipher_t cipher)
40 {
41 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { c.clear(); });
42 }
43
44 int botan_cipher_reset(botan_cipher_t cipher)
45 {
46 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { c.reset(); });
47 }
48
49 int botan_cipher_output_length(botan_cipher_t cipher, size_t in_len, size_t* out_len)
50 {
51 if(out_len == nullptr)
52 return BOTAN_FFI_ERROR_NULL_POINTER;
53
54 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *out_len = c.output_length(in_len); });
55 }
56
57 int botan_cipher_query_keylen(botan_cipher_t cipher,
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
67 int botan_cipher_get_keyspec(botan_cipher_t cipher,
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
82 int botan_cipher_set_key(botan_cipher_t cipher,
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
88 int botan_cipher_start(botan_cipher_t cipher_obj,
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
99 int botan_cipher_update(botan_cipher_t cipher_obj,
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 }
131 catch(Invalid_Authentication_Tag&)
132 {
133 return BOTAN_FFI_ERROR_BAD_MAC;
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
191 int botan_cipher_set_associated_data(botan_cipher_t cipher,
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 }
201 return BOTAN_FFI_ERROR_BAD_PARAMETER;
202 });
203 }
204
205 int botan_cipher_valid_nonce_length(botan_cipher_t cipher, size_t nl)
206 {
207 return BOTAN_FFI_RETURNING(Botan::Cipher_Mode, cipher, c, {
208 return c.valid_nonce_length(nl) ? 1 : 0;
209 });
210 }
211
212 int botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t* nl)
213 {
214 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *nl = c.default_nonce_length(); });
215 }
216
217 int botan_cipher_get_update_granularity(botan_cipher_t cipher, size_t* ug)
218 {
219 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *ug = c.update_granularity(); });
220 }
221
222 int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t* tl)
223 {
224 return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *tl = c.tag_size(); });
225 }
226
227 int 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}
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
Botan::AEAD_Mode
Definition: aead.h:23
Botan::Cipher_Mode
Definition: cipher_mode.h:29
Botan::Cipher_Mode::create
static std::unique_ptr< Cipher_Mode > create(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
Definition: cipher_mode.cpp:50
Botan::Cipher_Mode::default_nonce_length
virtual size_t default_nonce_length() const =0
Botan::Cipher_Mode::reset
virtual void reset()=0
Botan::Cipher_Mode::start
void start(const std::vector< uint8_t, Alloc > &nonce)
Definition: cipher_mode.h:69
Botan::Cipher_Mode::output_length
virtual size_t output_length(size_t input_length) const =0
Botan::Cipher_Mode::finish
virtual void finish(secure_vector< uint8_t > &final_block, size_t offset=0)=0
Botan::Cipher_Mode::tag_size
virtual size_t tag_size() const
Definition: cipher_mode.h:174
Botan::Cipher_Mode::update
void update(secure_vector< uint8_t > &buffer, size_t offset=0)
Definition: cipher_mode.h:112
Botan::Cipher_Mode::minimum_final_size
virtual size_t minimum_final_size() const =0
Botan::Cipher_Mode::update_granularity
virtual size_t update_granularity() const =0
Botan::Cipher_Mode::valid_nonce_length
virtual bool valid_nonce_length(size_t nonce_len) const =0
Botan::Invalid_Authentication_Tag
Definition: exceptn.h:291
Botan::Key_Length_Specification::minimum_keylength
size_t minimum_keylength() const
Definition: sym_algo.h:62
Botan::SymmetricAlgorithm::set_key
void set_key(const SymmetricKey &key)
Definition: sym_algo.h:147
Botan::SymmetricAlgorithm::clear
virtual void clear()=0
Botan::SymmetricAlgorithm::key_spec
virtual Key_Length_Specification key_spec() const =0
name
std::string name
Definition: commoncrypto_hash.cpp:24
final
int(* final)(unsigned char *, CTX *)
Definition: commoncrypto_hash.cpp:29
BOTAN_CIPHER_INIT_FLAG_ENCRYPT
#define BOTAN_CIPHER_INIT_FLAG_ENCRYPT
Definition: ffi.h:440
BOTAN_CIPHER_UPDATE_FLAG_FINAL
#define BOTAN_CIPHER_UPDATE_FLAG_FINAL
Definition: ffi.h:522
BOTAN_CIPHER_INIT_FLAG_MASK_DIRECTION
#define BOTAN_CIPHER_INIT_FLAG_MASK_DIRECTION
Definition: ffi.h:439
BOTAN_FFI_ERROR_NOT_IMPLEMENTED
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition: ffi.h:83
BOTAN_FFI_ERROR_NULL_POINTER
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition: ffi.h:77
BOTAN_FFI_SUCCESS
@ BOTAN_FFI_SUCCESS
Definition: ffi.h:63
BOTAN_FFI_ERROR_BAD_MAC
@ BOTAN_FFI_ERROR_BAD_MAC
Definition: ffi.h:67
BOTAN_FFI_ERROR_BAD_PARAMETER
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition: ffi.h:78
botan_cipher_t
struct botan_cipher_struct * botan_cipher_t
Definition: ffi.h:437
botan_cipher_update
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
botan_cipher_valid_nonce_length
int botan_cipher_valid_nonce_length(botan_cipher_t cipher, size_t nl)
Definition: ffi_cipher.cpp:205
botan_cipher_output_length
int botan_cipher_output_length(botan_cipher_t cipher, size_t in_len, size_t *out_len)
Definition: ffi_cipher.cpp:49
botan_cipher_reset
int botan_cipher_reset(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:44
botan_cipher_destroy
int botan_cipher_destroy(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:34
botan_cipher_name
int botan_cipher_name(botan_cipher_t cipher, char *name, size_t *name_len)
Definition: ffi_cipher.cpp:227
botan_cipher_set_associated_data
int botan_cipher_set_associated_data(botan_cipher_t cipher, const uint8_t *ad, size_t ad_len)
Definition: ffi_cipher.cpp:191
botan_cipher_start
int botan_cipher_start(botan_cipher_t cipher_obj, const uint8_t *nonce, size_t nonce_len)
Definition: ffi_cipher.cpp:88
botan_cipher_get_tag_length
int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t *tl)
Definition: ffi_cipher.cpp:222
botan_cipher_get_keyspec
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
botan_cipher_set_key
int botan_cipher_set_key(botan_cipher_t cipher, const uint8_t *key, size_t key_len)
Definition: ffi_cipher.cpp:82
botan_cipher_clear
int botan_cipher_clear(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:39
botan_cipher_get_default_nonce_length
int botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t *nl)
Definition: ffi_cipher.cpp:212
botan_cipher_init
int botan_cipher_init(botan_cipher_t *cipher, const char *cipher_name, uint32_t flags)
Definition: ffi_cipher.cpp:21
botan_cipher_query_keylen
int botan_cipher_query_keylen(botan_cipher_t cipher, size_t *out_minimum_keylength, size_t *out_maximum_keylength)
Definition: ffi_cipher.cpp:57
botan_cipher_get_update_granularity
int botan_cipher_get_update_granularity(botan_cipher_t cipher, size_t *ug)
Definition: ffi_cipher.cpp:217
BOTAN_FFI_DO
#define BOTAN_FFI_DO(T, obj, param, block)
Definition: ffi_util.h:92
BOTAN_FFI_CHECKED_DELETE
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition: ffi_util.h:129
BOTAN_FFI_RETURNING
#define BOTAN_FFI_RETURNING(T, obj, param, block)
Definition: ffi_util.h:101
Botan::PKCS11::flags
Flags flags(Flag flags)
Definition: p11.h:860
Botan_FFI
Definition: ffi.cpp:17
Botan_FFI::ffi_guard_thunk
int ffi_guard_thunk(const char *func_name, std::function< int()> thunk)
Definition: ffi.cpp:89
Botan_FFI::safe_get
T & safe_get(botan_struct< T, M > *p)
Definition: ffi_util.h:61
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
Definition: alg_id.cpp:13
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:133
Botan::Cipher_Dir
Cipher_Dir
Definition: cipher_mode.h:23
Botan::DECRYPTION
@ DECRYPTION
Definition: cipher_mode.h:23
Botan::ENCRYPTION
@ ENCRYPTION
Definition: cipher_mode.h:23
Botan::secure_vector
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
Botan_FFI::botan_struct
Definition: ffi_util.h:37