Botan  2.6.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 
21 int botan_cipher_init(botan_cipher_t* cipher, const char* cipher_name, uint32_t flags)
22  {
23  return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> 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  {
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  size_t* out_minimum_keylength,
46  size_t* out_maximum_keylength)
47  {
48  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, {
49  *out_minimum_keylength = c.key_spec().minimum_keylength();
50  *out_maximum_keylength = c.key_spec().maximum_keylength();
51  });
52  }
53 
55  const uint8_t* key, size_t key_len)
56  {
57  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { c.set_key(key, key_len); });
58  }
59 
61  const uint8_t* nonce, size_t nonce_len)
62  {
63  return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
64  Botan::Cipher_Mode& cipher = safe_get(cipher_obj);
65  cipher.start(nonce, nonce_len);
66  cipher_obj->m_buf.reserve(cipher.update_granularity());
67  return BOTAN_FFI_SUCCESS;
68  });
69  }
70 
72  uint32_t flags,
73  uint8_t output_ptr[],
74  size_t orig_output_size,
75  size_t* output_written,
76  const uint8_t input_ptr[],
77  size_t orig_input_size,
78  size_t* input_consumed)
79  {
80  return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
81 
82  size_t input_size = orig_input_size;
83  size_t output_size = orig_output_size;
84  const uint8_t* input = input_ptr;
85  uint8_t* output = output_ptr;
86 
87  using namespace Botan;
88  Cipher_Mode& cipher = safe_get(cipher_obj);
89  secure_vector<uint8_t>& mbuf = cipher_obj->m_buf;
90 
91  const bool final_input = (flags & BOTAN_CIPHER_UPDATE_FLAG_FINAL);
92 
93  if(final_input)
94  {
95  mbuf.assign(input, input + input_size);
96  *input_consumed = input_size;
97  *output_written = 0;
98 
99  try
100  {
101  cipher.finish(mbuf);
102  }
103  catch(Integrity_Failure&)
104  {
106  }
107 
108  *output_written = mbuf.size();
109 
110  if(mbuf.size() <= output_size)
111  {
112  copy_mem(output, mbuf.data(), mbuf.size());
113  mbuf.clear();
114  return BOTAN_FFI_SUCCESS;
115  }
116 
117  return -1;
118  }
119 
120  if(input_size == 0)
121  {
122  // Currently must take entire buffer in this case
123  *output_written = mbuf.size();
124  if(output_size >= mbuf.size())
125  {
126  copy_mem(output, mbuf.data(), mbuf.size());
127  mbuf.clear();
128  return BOTAN_FFI_SUCCESS;
129  }
130 
131  return -1;
132  }
133 
134  const size_t ud = cipher.update_granularity();
135  BOTAN_ASSERT(cipher.update_granularity() > cipher.minimum_final_size(), "logic error");
136 
137  mbuf.resize(ud);
138  size_t taken = 0, written = 0;
139 
140  while(input_size >= ud && output_size >= ud)
141  {
142  copy_mem(mbuf.data(), input, ud);
143  cipher.update(mbuf);
144 
145  input_size -= ud;
146  copy_mem(output, mbuf.data(), ud);
147  input += ud;
148  taken += ud;
149 
150  output_size -= ud;
151  output += ud;
152  written += ud;
153  }
154 
155  *output_written = written;
156  *input_consumed = taken;
157 
158  return BOTAN_FFI_SUCCESS;
159  });
160  }
161 
163  const uint8_t* ad,
164  size_t ad_len)
165  {
166  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, {
167  if(Botan::AEAD_Mode* aead = dynamic_cast<Botan::AEAD_Mode*>(&c))
168  {
169  aead->set_associated_data(ad, ad_len);
170  return BOTAN_FFI_SUCCESS;
171  }
173  });
174  }
175 
177  {
178  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { return c.valid_nonce_length(nl) ? 1 : 0; });
179  }
180 
182  {
183  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *nl = c.default_nonce_length(); });
184  }
185 
187  {
188  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *ug = c.update_granularity(); });
189  }
190 
192  {
193  return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *tl = c.tag_size(); });
194  }
195 
196 }
#define BOTAN_CIPHER_INIT_FLAG_ENCRYPT
Definition: ffi.h:375
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:71
int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t *tl)
Definition: ffi_cipher.cpp:191
#define BOTAN_CIPHER_INIT_FLAG_MASK_DIRECTION
Definition: ffi.h:374
int botan_cipher_init(botan_cipher_t *cipher, const char *cipher_name, uint32_t flags)
Definition: ffi_cipher.cpp:21
virtual void clear()=0
int botan_cipher_clear(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:39
void update(secure_vector< uint8_t > &buffer, size_t offset=0)
Definition: cipher_mode.h:115
int botan_cipher_start(botan_cipher_t cipher_obj, const uint8_t *nonce, size_t nonce_len)
Definition: ffi_cipher.cpp:60
virtual size_t update_granularity() const =0
int botan_cipher_destroy(botan_cipher_t cipher)
Definition: ffi_cipher.cpp:34
int ffi_guard_thunk(const char *func_name, Thunk thunk)
Definition: ffi_util.h:64
Flags flags(Flag flags)
Definition: p11.h:858
virtual size_t tag_size() const
Definition: cipher_mode.h:184
virtual Key_Length_Specification key_spec() const =0
int botan_cipher_set_key(botan_cipher_t cipher, const uint8_t *key, size_t key_len)
Definition: ffi_cipher.cpp:54
int botan_cipher_valid_nonce_length(botan_cipher_t cipher, size_t nl)
Definition: ffi_cipher.cpp:176
virtual size_t minimum_final_size() const =0
void start(const std::vector< uint8_t, Alloc > &nonce)
Definition: cipher_mode.h:72
virtual size_t default_nonce_length() const =0
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:30
#define BOTAN_CIPHER_UPDATE_FLAG_FINAL
Definition: ffi.h:398
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
Definition: alg_id.cpp:13
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition: ffi_util.h:126
T & safe_get(botan_struct< T, M > *p)
Definition: ffi_util.h:49
int botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t *nl)
Definition: ffi_cipher.cpp:181
void set_key(const std::vector< uint8_t, Alloc > &key)
Definition: cipher_mode.h:206
static std::unique_ptr< Cipher_Mode > create(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
Definition: cipher_mode.cpp:50
Cipher_Dir
Definition: cipher_mode.h:24
#define BOTAN_CURRENT_FUNCTION
Definition: compiler.h:143
int botan_cipher_get_update_granularity(botan_cipher_t cipher, size_t *ug)
Definition: ffi_cipher.cpp:186
int botan_cipher_set_associated_data(botan_cipher_t cipher, const uint8_t *ad, size_t ad_len)
Definition: ffi_cipher.cpp:162
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
struct botan_cipher_struct * botan_cipher_t
Definition: ffi.h:372
int botan_cipher_query_keylen(botan_cipher_t cipher, size_t *out_minimum_keylength, size_t *out_maximum_keylength)
Definition: ffi_cipher.cpp:44
#define BOTAN_FFI_DO(T, obj, param, block)
Definition: ffi_util.h:98
size_t minimum_keylength() const
Definition: key_spec.h:61
virtual bool valid_nonce_length(size_t nonce_len) const =0
virtual void finish(secure_vector< uint8_t > &final_block, size_t offset=0)=0