Botan  2.10.0
Crypto and TLS for C++11
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) {}
19  };
20 
22  {
23  return ffi_guard_thunk(__func__, [=]() -> int {
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)
29  *cipher = new botan_cipher_struct(mode.release());
30  return BOTAN_FFI_SUCCESS;
31  });
32  }
33 
35  {
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 
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, {
74  *out_minimum_keylength = c.key_spec().minimum_keylength();
76  *out_maximum_keylength = c.key_spec().maximum_keylength();
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);
125  *output_written = 0;
126 
127  try
128  {
129  cipher.finish(mbuf);
130  }
131  catch(Invalid_Authentication_Tag&)
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_DO(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_DO(Botan::Cipher_Mode, cipher, c, { return c.valid_nonce_length(nl) ? 1 : 0; });
208  }
209 
211  {
212  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *nl = c.default_nonce_length(); });
213  }
214 
216  {
217  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *ug = c.update_granularity(); });
218  }
219 
221  {
222  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *tl = c.tag_size(); });
223  }
224 
226  {
227  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, {
228  return write_str_output(name, name_len, c.name()); });
229  }
230 
231 }
int ffi_guard_thunk(const char *func_name, std::function< int()> thunk)
Definition: ffi.cpp:84
#define BOTAN_CIPHER_INIT_FLAG_ENCRYPT
Definition: ffi.h:421
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
uint32_t uint8_t size_t size_t const uint8_t size_t size_t * input_consumed
Definition: ffi.h:509
int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t *tl)
Definition: ffi_cipher.cpp:220
int botan_cipher_name(botan_cipher_t cipher, char *name, size_t *name_len)
Definition: ffi_cipher.cpp:225
#define BOTAN_CIPHER_INIT_FLAG_MASK_DIRECTION
Definition: ffi.h:420
uint32_t uint8_t output[]
Definition: ffi.h:509
size_t size_t size_t * out_keylength_modulo
Definition: ffi.h:404
size_t size_t * out_maximum_keylength
Definition: ffi.h:404
const uint8_t size_t nonce_len
Definition: ffi.h:501
int botan_cipher_init(botan_cipher_t *cipher, const char *cipher_name, uint32_t flags)
Definition: ffi_cipher.cpp:21
int botan_cipher_clear(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:39
int botan_cipher_start(botan_cipher_t cipher_obj, const uint8_t *nonce, size_t nonce_len)
Definition: ffi_cipher.cpp:88
int(* final)(unsigned char *, CTX *)
int botan_cipher_destroy(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:34
uint32_t uint8_t size_t output_size
Definition: ffi.h:509
int botan_cipher_set_key(botan_cipher_t cipher, const uint8_t *key, size_t key_len)
Definition: ffi_cipher.cpp:82
char * name
Definition: ffi.h:327
const botan_mp_t x
Definition: ffi.h:815
const uint8_t * ad
Definition: ffi.h:495
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
uint32_t uint8_t size_t size_t * output_written
Definition: ffi.h:509
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
int write_str_output(uint8_t out[], size_t *out_len, const std::string &str)
Definition: ffi_util.h:147
const char * cipher_name
Definition: ffi.h:657
uint32_t uint8_t size_t size_t const uint8_t size_t input_size
Definition: ffi.h:509
#define BOTAN_CIPHER_UPDATE_FLAG_FINAL
Definition: ffi.h:503
size_t uint8_t size_t * out_len
Definition: ffi.h:171
void BlockCipher * cipher
Definition: package.h:29
void uint8_t const uint8_t RandomNumberGenerator Newhope_Mode mode
Definition: newhope.h:75
size_t nl
Definition: ffi.h:442
secure_vector< uint8_t > const uint8_t size_t const uint8_t size_t RandomNumberGenerator const std::string & aead
Definition: mceies.h:30
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:122
Definition: alg_id.cpp:13
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition: ffi_util.h:116
const uint8_t * key
Definition: ffi.h:359
T & safe_get(botan_struct< T, M > *p)
Definition: ffi_util.h:61
int botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t *nl)
Definition: ffi_cipher.cpp:210
size_t const uint8_t input[]
Definition: base32.h:30
size_t char uint32_t flags
Definition: ffi.h:162
BigInt const BigInt const BigInt & c
Definition: numthry.h:25
Cipher_Dir
Definition: cipher_mode.h:23
int botan_cipher_get_update_granularity(botan_cipher_t cipher, size_t *ug)
Definition: ffi_cipher.cpp:215
int botan_cipher_set_associated_data(botan_cipher_t cipher, const uint8_t *ad, size_t ad_len)
Definition: ffi_cipher.cpp:191
size_t * ug
Definition: ffi.h:458
char size_t * name_len
Definition: ffi.h:327
const uint8_t * nonce
Definition: ffi.h:501
int botan_cipher_reset(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:44
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
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
const uint8_t size_t ad_len
Definition: ffi.h:495
size_t in_len
Definition: ffi.h:171
struct botan_cipher_struct * botan_cipher_t
Definition: ffi.h:418
int botan_cipher_query_keylen(botan_cipher_t cipher, size_t *out_minimum_keylength, size_t *out_maximum_keylength)
Definition: ffi_cipher.cpp:57
#define BOTAN_FFI_DO(T, obj, param, block)
Definition: ffi_util.h:88
size_t * out_minimum_keylength
Definition: ffi.h:404
const uint8_t size_t key_len
Definition: ffi.h:359