summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/ffi/ffi_pk_op.cpp
blob: 2efb297aca80b67f9f2cb508b1492de5ed489c96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/*
* (C) 2015,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/ffi.h>
#include <botan/internal/ffi_util.h>
#include <botan/internal/ffi_pkey.h>
#include <botan/internal/ffi_rng.h>
#include <botan/pubkey.h>

extern "C" {

using namespace Botan_FFI;

BOTAN_FFI_DECLARE_STRUCT(botan_pk_op_encrypt_struct, Botan::PK_Encryptor, 0x891F3FC3);
BOTAN_FFI_DECLARE_STRUCT(botan_pk_op_decrypt_struct, Botan::PK_Decryptor, 0x912F3C37);
BOTAN_FFI_DECLARE_STRUCT(botan_pk_op_sign_struct, Botan::PK_Signer, 0x1AF0C39F);
BOTAN_FFI_DECLARE_STRUCT(botan_pk_op_verify_struct, Botan::PK_Verifier, 0x2B91F936);
BOTAN_FFI_DECLARE_STRUCT(botan_pk_op_ka_struct, Botan::PK_Key_Agreement, 0x2939CAB1);

int botan_pk_op_encrypt_create(botan_pk_op_encrypt_t* op,
                               botan_pubkey_t key_obj,
                               const char* padding,
                               uint32_t flags)
   {
   if(op == nullptr)
      return BOTAN_FFI_ERROR_NULL_POINTER;

   if(flags != 0 && flags != BOTAN_PUBKEY_DER_FORMAT_SIGNATURE)
      return BOTAN_FFI_ERROR_BAD_FLAG;

   return ffi_guard_thunk(__func__, [=]() -> int {
      *op = nullptr;

      std::unique_ptr<Botan::PK_Encryptor> pk(new Botan::PK_Encryptor_EME(safe_get(key_obj), Botan::system_rng(), padding));
      *op = new botan_pk_op_encrypt_struct(pk.release());
      return BOTAN_FFI_SUCCESS;
      });
   }

int botan_pk_op_encrypt_destroy(botan_pk_op_encrypt_t op)
   {
   return BOTAN_FFI_CHECKED_DELETE(op);
   }

int botan_pk_op_encrypt_output_length(botan_pk_op_encrypt_t op, size_t ptext_len, size_t* ctext_len)
   {
   if(ctext_len == nullptr)
      return BOTAN_FFI_ERROR_NULL_POINTER;
   return BOTAN_FFI_DO(Botan::PK_Encryptor, op, o, { *ctext_len = o.ciphertext_length(ptext_len); });
   }

int botan_pk_op_encrypt(botan_pk_op_encrypt_t op,
                        botan_rng_t rng_obj,
                        uint8_t out[], size_t* out_len,
                        const uint8_t plaintext[], size_t plaintext_len)
   {
   return BOTAN_FFI_DO(Botan::PK_Encryptor, op, o, {
      return write_vec_output(out, out_len, o.encrypt(plaintext, plaintext_len, safe_get(rng_obj)));
      });
   }

/*
* Public Key Decryption
*/
int botan_pk_op_decrypt_create(botan_pk_op_decrypt_t* op,
                               botan_privkey_t key_obj,
                               const char* padding,
                               uint32_t flags)
   {
   if(op == nullptr)
      return BOTAN_FFI_ERROR_NULL_POINTER;

   if(flags != 0)
      return BOTAN_FFI_ERROR_BAD_FLAG;

   return ffi_guard_thunk(__func__, [=]() -> int {
      *op = nullptr;

      std::unique_ptr<Botan::PK_Decryptor> pk(new Botan::PK_Decryptor_EME(safe_get(key_obj), Botan::system_rng(), padding));
      *op = new botan_pk_op_decrypt_struct(pk.release());
      return BOTAN_FFI_SUCCESS;
      });
   }

int botan_pk_op_decrypt_destroy(botan_pk_op_decrypt_t op)
   {
   return BOTAN_FFI_CHECKED_DELETE(op);
   }

int botan_pk_op_decrypt_output_length(botan_pk_op_decrypt_t op, size_t ctext_len, size_t* ptext_len)
   {
   if(ptext_len == nullptr)
      return BOTAN_FFI_ERROR_NULL_POINTER;
   return BOTAN_FFI_DO(Botan::PK_Decryptor, op, o, { *ptext_len = o.plaintext_length(ctext_len); });
   }

int botan_pk_op_decrypt(botan_pk_op_decrypt_t op,
                        uint8_t out[], size_t* out_len,
                        const uint8_t ciphertext[], size_t ciphertext_len)
   {
   return BOTAN_FFI_DO(Botan::PK_Decryptor, op, o, {
      return write_vec_output(out, out_len, o.decrypt(ciphertext, ciphertext_len));
      });
   }

/*
* Signature Generation
*/
int botan_pk_op_sign_create(botan_pk_op_sign_t* op,
                            botan_privkey_t key_obj,
                            const char* hash,
                            uint32_t flags)
   {
   if(op == nullptr)
      return BOTAN_FFI_ERROR_NULL_POINTER;

   if(flags != 0 && flags != BOTAN_PUBKEY_DER_FORMAT_SIGNATURE)
      return BOTAN_FFI_ERROR_BAD_FLAG;

   return ffi_guard_thunk(__func__, [=]() -> int {
      *op = nullptr;

      auto format = (flags & BOTAN_PUBKEY_DER_FORMAT_SIGNATURE) ? Botan::DER_SEQUENCE : Botan::IEEE_1363;

      std::unique_ptr<Botan::PK_Signer> pk(new Botan::PK_Signer(safe_get(key_obj), Botan::system_rng(), hash, format));
      *op = new botan_pk_op_sign_struct(pk.release());
      return BOTAN_FFI_SUCCESS;
      });
   }

int botan_pk_op_sign_destroy(botan_pk_op_sign_t op)
   {
   return BOTAN_FFI_CHECKED_DELETE(op);
   }

int botan_pk_op_sign_output_length(botan_pk_op_sign_t op, size_t* sig_len)
   {
   if(sig_len == nullptr)
      return BOTAN_FFI_ERROR_NULL_POINTER;

   return BOTAN_FFI_DO(Botan::PK_Signer, op, o, { *sig_len = o.signature_length(); });
   }

int botan_pk_op_sign_update(botan_pk_op_sign_t op, const uint8_t in[], size_t in_len)
   {
   return BOTAN_FFI_DO(Botan::PK_Signer, op, o, { o.update(in, in_len); });
   }

int botan_pk_op_sign_finish(botan_pk_op_sign_t op, botan_rng_t rng_obj, uint8_t out[], size_t* out_len)
   {
   return BOTAN_FFI_DO(Botan::PK_Signer, op, o, {
      return write_vec_output(out, out_len, o.signature(safe_get(rng_obj)));
      });
   }

int botan_pk_op_verify_create(botan_pk_op_verify_t* op,
                              botan_pubkey_t key_obj,
                              const char* hash,
                              uint32_t flags)
   {
   if(op == nullptr)
      return BOTAN_FFI_ERROR_NULL_POINTER;

   if(flags != 0 && flags != BOTAN_PUBKEY_DER_FORMAT_SIGNATURE)
      return BOTAN_FFI_ERROR_BAD_FLAG;

   return ffi_guard_thunk(__func__, [=]() -> int {
      *op = nullptr;
      auto format = (flags & BOTAN_PUBKEY_DER_FORMAT_SIGNATURE) ? Botan::DER_SEQUENCE : Botan::IEEE_1363;
      std::unique_ptr<Botan::PK_Verifier> pk(new Botan::PK_Verifier(safe_get(key_obj), hash, format));
      *op = new botan_pk_op_verify_struct(pk.release());
      return BOTAN_FFI_SUCCESS;
      });
   }

int botan_pk_op_verify_destroy(botan_pk_op_verify_t op)
   {
   return BOTAN_FFI_CHECKED_DELETE(op);
   }

int botan_pk_op_verify_update(botan_pk_op_verify_t op, const uint8_t in[], size_t in_len)
   {
   return BOTAN_FFI_DO(Botan::PK_Verifier, op, o, { o.update(in, in_len); });
   }

int botan_pk_op_verify_finish(botan_pk_op_verify_t op, const uint8_t sig[], size_t sig_len)
   {
   return BOTAN_FFI_RETURNING(Botan::PK_Verifier, op, o, {
      const bool legit = o.check_signature(sig, sig_len);

      if(legit)
         return BOTAN_FFI_SUCCESS;
      else
         return BOTAN_FFI_INVALID_VERIFIER;
      });
   }

int botan_pk_op_key_agreement_create(botan_pk_op_ka_t* op,
                                     botan_privkey_t key_obj,
                                     const char* kdf,
                                     uint32_t flags)
   {
   if(op == nullptr)
      return BOTAN_FFI_ERROR_NULL_POINTER;

   if(flags != 0)
      return BOTAN_FFI_ERROR_BAD_FLAG;

   return ffi_guard_thunk(__func__, [=]() -> int {
      *op = nullptr;
      std::unique_ptr<Botan::PK_Key_Agreement> pk(new Botan::PK_Key_Agreement(safe_get(key_obj), Botan::system_rng(), kdf));
      *op = new botan_pk_op_ka_struct(pk.release());
      return BOTAN_FFI_SUCCESS;
      });
   }

int botan_pk_op_key_agreement_destroy(botan_pk_op_ka_t op)
   {
   return BOTAN_FFI_CHECKED_DELETE(op);
   }

int botan_pk_op_key_agreement_export_public(botan_privkey_t key,
                                            uint8_t out[], size_t* out_len)
   {
   return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
      if(auto kak = dynamic_cast<const Botan::PK_Key_Agreement_Key*>(&k))
         return write_vec_output(out, out_len, kak->public_value());
      return BOTAN_FFI_ERROR_BAD_FLAG;
      });
   }

int botan_pk_op_key_agreement_size(botan_pk_op_ka_t op, size_t* out_len)
   {
   return BOTAN_FFI_DO(Botan::PK_Key_Agreement, op, o, {
      if(out_len == nullptr)
         return BOTAN_FFI_ERROR_NULL_POINTER;
      *out_len = o.agreed_value_size();
      });
   }

int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
                              uint8_t out[], size_t* out_len,
                              const uint8_t other_key[], size_t other_key_len,
                              const uint8_t salt[], size_t salt_len)
   {
   return BOTAN_FFI_DO(Botan::PK_Key_Agreement, op, o, {
      auto k = o.derive_key(*out_len, other_key, other_key_len, salt, salt_len).bits_of();
      return write_vec_output(out, out_len, k);
      });
   }

}