~ubuntu-branches/debian/sid/botan/sid

« back to all changes in this revision

Viewing changes to src/lib/ffi/ffi_pkey_algs.cpp

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2018-03-01 22:23:25 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20180301222325-7p7vc45gu3hta34d
Tags: 2.4.0-2
* Don't remove .doctrees from the manual if it doesn't exist.
* Don't specify parallel to debhelper.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
* (C) 2015,2017 Jack Lloyd
 
3
* (C) 2017 Ribose Inc
 
4
*
 
5
* Botan is released under the Simplified BSD License (see license.txt)
 
6
*/
 
7
 
 
8
#include <botan/ffi.h>
 
9
#include <botan/hash.h>
 
10
#include <botan/internal/ffi_util.h>
 
11
#include <botan/internal/ffi_pkey.h>
 
12
#include <botan/internal/ffi_rng.h>
 
13
#include <botan/internal/ffi_mp.h>
 
14
 
 
15
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
 
16
  #include <botan/ecc_key.h>
 
17
#endif
 
18
 
 
19
#if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY)
 
20
  #include <botan/dl_algo.h>
 
21
#endif
 
22
 
 
23
#if defined(BOTAN_HAS_RSA)
 
24
  #include <botan/rsa.h>
 
25
#endif
 
26
 
 
27
#if defined(BOTAN_HAS_ELGAMAL)
 
28
  #include <botan/elgamal.h>
 
29
#endif
 
30
 
 
31
#if defined(BOTAN_HAS_DSA)
 
32
  #include <botan/dsa.h>
 
33
#endif
 
34
 
 
35
#if defined(BOTAN_HAS_ECDSA)
 
36
  #include <botan/ecdsa.h>
 
37
#endif
 
38
 
 
39
#if defined(BOTAN_HAS_SM2)
 
40
  #include <botan/sm2.h>
 
41
  #include <botan/sm2_enc.h>
 
42
#endif
 
43
 
 
44
#if defined(BOTAN_HAS_ECDH)
 
45
  #include <botan/ecdh.h>
 
46
#endif
 
47
 
 
48
#if defined(BOTAN_HAS_CURVE_25519)
 
49
  #include <botan/curve25519.h>
 
50
#endif
 
51
 
 
52
#if defined(BOTAN_HAS_ED25519)
 
53
  #include <botan/ed25519.h>
 
54
#endif
 
55
 
 
56
#if defined(BOTAN_HAS_MCELIECE)
 
57
  #include <botan/mceliece.h>
 
58
#endif
 
59
 
 
60
#if defined(BOTAN_HAS_MCEIES)
 
61
  #include <botan/mceies.h>
 
62
#endif
 
63
 
 
64
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
 
65
  #include <botan/dh.h>
 
66
#endif
 
67
 
 
68
 
 
69
namespace {
 
70
 
 
71
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
 
72
 
 
73
// These are always called within an existing try/catch block
 
74
 
 
75
template<class ECPrivateKey_t>
 
76
int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key,
 
77
                    const Botan::BigInt& scalar,
 
78
                    const char* curve_name)
 
79
   {
 
80
   if(curve_name == nullptr)
 
81
      return BOTAN_FFI_ERROR_NULL_POINTER;
 
82
 
 
83
   Botan::Null_RNG null_rng;
 
84
   Botan::EC_Group grp(curve_name);
 
85
   key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
 
86
   return BOTAN_FFI_SUCCESS;
 
87
   }
 
88
 
 
89
template<class ECPublicKey_t>
 
90
int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
 
91
                   const Botan::BigInt& public_x,
 
92
                   const Botan::BigInt& public_y,
 
93
                   const char* curve_name)
 
94
   {
 
95
   if(curve_name == nullptr)
 
96
      return BOTAN_FFI_ERROR_NULL_POINTER;
 
97
 
 
98
   Botan::EC_Group grp(curve_name);
 
99
   Botan::PointGFp uncompressed_point(grp.get_curve(), public_x, public_y);
 
100
   key.reset(new ECPublicKey_t(grp, uncompressed_point));
 
101
   return BOTAN_FFI_SUCCESS;
 
102
   }
 
103
 
 
104
#endif
 
105
 
 
106
Botan::BigInt pubkey_get_field(const Botan::Public_Key& key,
 
107
                               const std::string& field)
 
108
   {
 
109
   // Maybe this should be `return key.get_integer_field(field_name)`?
 
110
 
 
111
#if defined(BOTAN_HAS_RSA)
 
112
   if(const Botan::RSA_PublicKey* rsa = dynamic_cast<const Botan::RSA_PublicKey*>(&key))
 
113
      {
 
114
      if(field == "n")
 
115
         return rsa->get_n();
 
116
      else if(field == "e")
 
117
         return rsa->get_e();
 
118
      else
 
119
         throw Botan::Exception("Field not supported");
 
120
      }
 
121
#endif
 
122
 
 
123
#if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY)
 
124
   // Handles DSA, ElGamal, etc
 
125
   if(const Botan::DL_Scheme_PublicKey* dl = dynamic_cast<const Botan::DL_Scheme_PublicKey*>(&key))
 
126
      {
 
127
      if(field == "p")
 
128
         return dl->group_p();
 
129
      else if(field == "q")
 
130
         return dl->group_q();
 
131
      else if(field == "g")
 
132
         return dl->group_g();
 
133
      else if(field == "y")
 
134
         return dl->get_y();
 
135
      else
 
136
         throw Botan::Exception("Field not supported");
 
137
      }
 
138
#endif
 
139
 
 
140
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
 
141
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key))
 
142
      {
 
143
      if(field == "public_x")
 
144
         return ecc->public_point().get_affine_x();
 
145
      else if(field == "public_y")
 
146
         return ecc->public_point().get_affine_y();
 
147
      else if(field == "base_x")
 
148
         return ecc->domain().get_base_point().get_affine_x();
 
149
      else if(field == "base_y")
 
150
         return ecc->domain().get_base_point().get_affine_y();
 
151
      else if(field == "p")
 
152
         return ecc->domain().get_curve().get_p();
 
153
      else if(field == "a")
 
154
         return ecc->domain().get_curve().get_a();
 
155
      else if(field == "b")
 
156
         return ecc->domain().get_curve().get_b();
 
157
      else if(field == "cofactor")
 
158
         return ecc->domain().get_cofactor();
 
159
      else if(field == "order")
 
160
         return ecc->domain().get_order();
 
161
      else
 
162
         throw Botan::Exception("Field not supported");
 
163
      }
 
164
#endif
 
165
 
 
166
   // Some other algorithm type not supported by this function
 
167
   throw Botan::Exception("Unsupported algorithm type for botan_pubkey_get_field");
 
168
   }
 
169
 
 
170
Botan::BigInt privkey_get_field(const Botan::Private_Key& key,
 
171
                                const std::string& field)
 
172
   {
 
173
   //return key.get_integer_field(field);
 
174
 
 
175
#if defined(BOTAN_HAS_RSA)
 
176
 
 
177
   if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&key))
 
178
      {
 
179
      if(field == "p")
 
180
         return rsa->get_p();
 
181
      else if(field == "q")
 
182
         return rsa->get_q();
 
183
      else if(field == "d")
 
184
         return rsa->get_d();
 
185
      else if(field == "c")
 
186
         return rsa->get_c();
 
187
      else if(field == "d1")
 
188
         return rsa->get_d1();
 
189
      else if(field == "d2")
 
190
         return rsa->get_d2();
 
191
      else
 
192
         return pubkey_get_field(key, field);
 
193
      }
 
194
#endif
 
195
 
 
196
#if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY)
 
197
   // Handles DSA, ElGamal, etc
 
198
   if(const Botan::DL_Scheme_PrivateKey* dl = dynamic_cast<const Botan::DL_Scheme_PrivateKey*>(&key))
 
199
      {
 
200
      if(field == "x")
 
201
         return dl->get_x();
 
202
      else
 
203
         return pubkey_get_field(key, field);
 
204
      }
 
205
#endif
 
206
 
 
207
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
 
208
   if(const Botan::EC_PrivateKey* ecc = dynamic_cast<const Botan::EC_PrivateKey*>(&key))
 
209
      {
 
210
      if(field == "x")
 
211
         return ecc->private_value();
 
212
      else
 
213
         return pubkey_get_field(key, field);
 
214
      }
 
215
#endif
 
216
 
 
217
   // Some other algorithm type not supported by this function
 
218
   throw Botan::Exception("Unsupported algorithm type for botan_privkey_get_field");
 
219
   }
 
220
 
 
221
}
 
222
 
 
223
extern "C" {
 
224
 
 
225
using namespace Botan_FFI;
 
226
 
 
227
int botan_pubkey_get_field(botan_mp_t output,
 
228
                           botan_pubkey_t key,
 
229
                           const char* field_name_cstr)
 
230
   {
 
231
   if(field_name_cstr == nullptr)
 
232
      return BOTAN_FFI_ERROR_NULL_POINTER;
 
233
 
 
234
   const std::string field_name(field_name_cstr);
 
235
 
 
236
   return BOTAN_FFI_DO(Botan::Public_Key, key, k, {
 
237
      safe_get(output) = pubkey_get_field(k, field_name);
 
238
      });
 
239
   }
 
240
 
 
241
int botan_privkey_get_field(botan_mp_t output,
 
242
                                      botan_privkey_t key,
 
243
                                      const char* field_name_cstr)
 
244
   {
 
245
   if(field_name_cstr == nullptr)
 
246
      return BOTAN_FFI_ERROR_NULL_POINTER;
 
247
 
 
248
   const std::string field_name(field_name_cstr);
 
249
 
 
250
   return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
 
251
      safe_get(output) = privkey_get_field(k, field_name);
 
252
      });
 
253
   }
 
254
 
 
255
/* RSA specific operations */
 
256
 
 
257
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits)
 
258
   {
 
259
   if(n_bits < 1024 || n_bits > 16*1024)
 
260
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
 
261
 
 
262
   std::string n_str = std::to_string(n_bits);
 
263
 
 
264
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
 
265
   }
 
266
 
 
267
int botan_privkey_load_rsa(botan_privkey_t* key,
 
268
                           botan_mp_t rsa_p, botan_mp_t rsa_q, botan_mp_t rsa_e)
 
269
   {
 
270
#if defined(BOTAN_HAS_RSA)
 
271
   *key = nullptr;
 
272
 
 
273
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
274
      *key = new botan_privkey_struct(new Botan::RSA_PrivateKey(safe_get(rsa_p),
 
275
                                                                safe_get(rsa_q),
 
276
                                                                safe_get(rsa_e)));
 
277
      return BOTAN_FFI_SUCCESS;
 
278
      });
 
279
#else
 
280
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
 
281
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
282
#endif
 
283
   }
 
284
 
 
285
int botan_pubkey_load_rsa(botan_pubkey_t* key,
 
286
                          botan_mp_t n, botan_mp_t e)
 
287
   {
 
288
#if defined(BOTAN_HAS_RSA)
 
289
   *key = nullptr;
 
290
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
291
      *key = new botan_pubkey_struct(new Botan::RSA_PublicKey(safe_get(n), safe_get(e)));
 
292
      return BOTAN_FFI_SUCCESS;
 
293
      });
 
294
#else
 
295
   BOTAN_UNUSED(key, n, e);
 
296
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
297
#endif
 
298
   }
 
299
 
 
300
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key)
 
301
   {
 
302
   return botan_privkey_get_field(p, key, "p");
 
303
   }
 
304
 
 
305
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key)
 
306
   {
 
307
   return botan_privkey_get_field(q, key, "q");
 
308
   }
 
309
 
 
310
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key)
 
311
   {
 
312
   return botan_privkey_get_field(n, key, "n");
 
313
   }
 
314
 
 
315
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key)
 
316
   {
 
317
   return botan_privkey_get_field(e, key, "e");
 
318
   }
 
319
 
 
320
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key)
 
321
   {
 
322
   return botan_privkey_get_field(d, key, "d");
 
323
   }
 
324
 
 
325
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key)
 
326
   {
 
327
   return botan_pubkey_get_field(e, key, "e");
 
328
   }
 
329
 
 
330
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key)
 
331
   {
 
332
   return botan_pubkey_get_field(n, key, "n");
 
333
   }
 
334
 
 
335
/* DSA specific operations */
 
336
 
 
337
int botan_privkey_load_dsa(botan_privkey_t* key,
 
338
                           botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t x)
 
339
   {
 
340
#if defined(BOTAN_HAS_DSA)
 
341
   *key = nullptr;
 
342
 
 
343
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
344
      Botan::Null_RNG null_rng;
 
345
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
 
346
      *key = new botan_privkey_struct(new Botan::DSA_PrivateKey(null_rng, group, safe_get(x)));
 
347
      return BOTAN_FFI_SUCCESS;
 
348
      });
 
349
#else
 
350
   BOTAN_UNUSED(key, p, q, g, x);
 
351
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
352
#endif
 
353
   }
 
354
 
 
355
int botan_pubkey_load_dsa(botan_pubkey_t* key,
 
356
                          botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t y)
 
357
   {
 
358
#if defined(BOTAN_HAS_DSA)
 
359
   *key = nullptr;
 
360
 
 
361
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
362
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
 
363
      *key = new botan_pubkey_struct(new Botan::DSA_PublicKey(group, safe_get(y)));
 
364
      return BOTAN_FFI_SUCCESS;
 
365
      });
 
366
#else
 
367
   BOTAN_UNUSED(key, p, q, g, y);
 
368
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
369
#endif
 
370
   }
 
371
 
 
372
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key)
 
373
   {
 
374
   return botan_privkey_get_field(x, key, "x");
 
375
   }
 
376
 
 
377
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key)
 
378
   {
 
379
   return botan_pubkey_get_field(p, key, "p");
 
380
   }
 
381
 
 
382
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key)
 
383
   {
 
384
   return botan_pubkey_get_field(q, key, "q");
 
385
   }
 
386
 
 
387
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key)
 
388
   {
 
389
   return botan_pubkey_get_field(g, key, "g");
 
390
   }
 
391
 
 
392
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key)
 
393
   {
 
394
   return botan_pubkey_get_field(y, key, "y");
 
395
   }
 
396
 
 
397
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str)
 
398
   {
 
399
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
 
400
   }
 
401
 
 
402
/* ECDSA specific operations */
 
403
 
 
404
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
 
405
                            const botan_mp_t public_x,
 
406
                            const botan_mp_t public_y,
 
407
                            const char* curve_name)
 
408
   {
 
409
#if defined(BOTAN_HAS_ECDSA)
 
410
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
411
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
 
412
 
 
413
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
 
414
      if(rc == BOTAN_FFI_SUCCESS)
 
415
         *key = new botan_pubkey_struct(p_key.release());
 
416
 
 
417
      return rc;
 
418
      });
 
419
#else
 
420
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
 
421
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
422
#endif
 
423
   }
 
424
 
 
425
int botan_privkey_load_ecdsa(botan_privkey_t* key,
 
426
                             const botan_mp_t scalar,
 
427
                             const char* curve_name)
 
428
   {
 
429
#if defined(BOTAN_HAS_ECDSA)
 
430
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
431
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
 
432
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
 
433
      if(rc == BOTAN_FFI_SUCCESS)
 
434
         *key = new botan_privkey_struct(p_key.release());
 
435
      return rc;
 
436
      });
 
437
#else
 
438
   BOTAN_UNUSED(key, scalar, curve_name);
 
439
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
440
#endif
 
441
   }
 
442
 
 
443
/* ElGamal specific operations */
 
444
 
 
445
int botan_pubkey_load_elgamal(botan_pubkey_t* key,
 
446
                              botan_mp_t p, botan_mp_t g, botan_mp_t y)
 
447
   {
 
448
#if defined(BOTAN_HAS_ELGAMAL)
 
449
   *key = nullptr;
 
450
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
451
      Botan::DL_Group group(safe_get(p), safe_get(g));
 
452
      *key = new botan_pubkey_struct(new Botan::ElGamal_PublicKey(group, safe_get(y)));
 
453
      return BOTAN_FFI_SUCCESS;
 
454
      });
 
455
#else
 
456
   BOTAN_UNUSED(key, p, g, y);
 
457
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
458
#endif
 
459
   }
 
460
 
 
461
int botan_privkey_load_elgamal(botan_privkey_t* key,
 
462
                               botan_mp_t p, botan_mp_t g, botan_mp_t x)
 
463
   {
 
464
#if defined(BOTAN_HAS_ELGAMAL)
 
465
   *key = nullptr;
 
466
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
467
      Botan::Null_RNG null_rng;
 
468
      Botan::DL_Group group(safe_get(p), safe_get(g));
 
469
      *key = new botan_privkey_struct(new Botan::ElGamal_PrivateKey(null_rng, group, safe_get(x)));
 
470
      return BOTAN_FFI_SUCCESS;
 
471
      });
 
472
#else
 
473
   BOTAN_UNUSED(key, p, g, x);
 
474
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
475
#endif
 
476
   }
 
477
 
 
478
/* Diffie Hellman specific operations */
 
479
 
 
480
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str)
 
481
   {
 
482
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
 
483
   }
 
484
 
 
485
int botan_privkey_load_dh(botan_privkey_t* key,
 
486
                          botan_mp_t p, botan_mp_t g, botan_mp_t x)
 
487
   {
 
488
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
 
489
   *key = nullptr;
 
490
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
491
      Botan::Null_RNG null_rng;
 
492
      Botan::DL_Group group(safe_get(p), safe_get(g));
 
493
      *key = new botan_privkey_struct(new Botan::DH_PrivateKey(null_rng, group, safe_get(x)));
 
494
      return BOTAN_FFI_SUCCESS;
 
495
      });
 
496
#else
 
497
   BOTAN_UNUSED(key, p, g, x);
 
498
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
499
#endif
 
500
   }
 
501
 
 
502
int botan_pubkey_load_dh(botan_pubkey_t* key,
 
503
                         botan_mp_t p, botan_mp_t g, botan_mp_t y)
 
504
   {
 
505
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
 
506
   *key = nullptr;
 
507
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
508
      Botan::DL_Group group(safe_get(p), safe_get(g));
 
509
      *key = new botan_pubkey_struct(new Botan::DH_PublicKey(group, safe_get(y)));
 
510
      return BOTAN_FFI_SUCCESS;
 
511
      });
 
512
#else
 
513
   BOTAN_UNUSED(key, p, g, y);
 
514
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
515
#endif
 
516
   }
 
517
 
 
518
/* ECDH + x25519 specific operations */
 
519
 
 
520
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str)
 
521
   {
 
522
   if(param_str == nullptr)
 
523
      return BOTAN_FFI_ERROR_NULL_POINTER;
 
524
 
 
525
   const std::string params(param_str);
 
526
 
 
527
   if(params == "curve25519")
 
528
      return botan_privkey_create(key_obj, "Curve25519", "", rng_obj);
 
529
 
 
530
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
 
531
   }
 
532
 
 
533
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
 
534
                           const botan_mp_t public_x,
 
535
                           const botan_mp_t public_y,
 
536
                           const char* curve_name)
 
537
   {
 
538
#if defined(BOTAN_HAS_ECDH)
 
539
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
540
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
 
541
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
 
542
 
 
543
      if(rc == BOTAN_FFI_SUCCESS)
 
544
         *key = new botan_pubkey_struct(p_key.release());
 
545
      return rc;
 
546
      });
 
547
#else
 
548
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
 
549
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
550
#endif
 
551
   }
 
552
 
 
553
int botan_privkey_load_ecdh(botan_privkey_t* key,
 
554
                            const botan_mp_t scalar,
 
555
                            const char* curve_name)
 
556
   {
 
557
#if defined(BOTAN_HAS_ECDH)
 
558
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
559
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
 
560
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
 
561
      if(rc == BOTAN_FFI_SUCCESS)
 
562
         *key = new botan_privkey_struct(p_key.release());
 
563
      return rc;
 
564
      });
 
565
#else
 
566
   BOTAN_UNUSED(key, scalar, curve_name);
 
567
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
568
#endif
 
569
   }
 
570
 
 
571
/* SM2 specific operations */
 
572
 
 
573
int botan_pubkey_sm2_compute_za(uint8_t out[],
 
574
                                size_t* out_len,
 
575
                                const char* ident,
 
576
                                const char* hash_algo,
 
577
                                const botan_pubkey_t key)
 
578
   {
 
579
   if(out == nullptr || out_len == nullptr)
 
580
      return BOTAN_FFI_ERROR_NULL_POINTER;
 
581
   if(ident == nullptr || hash_algo == nullptr || key == nullptr)
 
582
      return BOTAN_FFI_ERROR_NULL_POINTER;
 
583
 
 
584
#if defined(BOTAN_HAS_SM2)
 
585
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
586
      const Botan::Public_Key& pub_key = safe_get(key);
 
587
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
 
588
 
 
589
      if(ec_key == nullptr)
 
590
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
 
591
 
 
592
      if(ec_key->algo_name() != "SM2_Sig" && ec_key->algo_name() != "SM2_Enc")
 
593
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
 
594
 
 
595
      const std::string ident_str(ident);
 
596
      std::unique_ptr<Botan::HashFunction> hash =
 
597
         Botan::HashFunction::create_or_throw(hash_algo);
 
598
 
 
599
      const std::vector<uint8_t> za =
 
600
         Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), ec_key->public_point());
 
601
 
 
602
      return write_vec_output(out, out_len, za);
 
603
      });
 
604
#else
 
605
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
606
#endif
 
607
   }
 
608
 
 
609
int botan_pubkey_load_sm2(botan_pubkey_t* key,
 
610
                          const botan_mp_t public_x,
 
611
                          const botan_mp_t public_y,
 
612
                          const char* curve_name)
 
613
   {
 
614
#if defined(BOTAN_HAS_SM2)
 
615
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
616
      std::unique_ptr<Botan::SM2_Signature_PublicKey> p_key;
 
617
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name))
 
618
         {
 
619
         *key = new botan_pubkey_struct(p_key.release());
 
620
         return BOTAN_FFI_SUCCESS;
 
621
         }
 
622
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
 
623
      });
 
624
#else
 
625
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
 
626
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
627
#endif
 
628
   }
 
629
 
 
630
int botan_privkey_load_sm2(botan_privkey_t* key,
 
631
                           const botan_mp_t scalar,
 
632
                           const char* curve_name)
 
633
   {
 
634
#if defined(BOTAN_HAS_SM2)
 
635
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
636
      std::unique_ptr<Botan::SM2_Signature_PrivateKey> p_key;
 
637
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
 
638
 
 
639
      if(rc == BOTAN_FFI_SUCCESS)
 
640
         *key = new botan_privkey_struct(p_key.release());
 
641
      return rc;
 
642
      });
 
643
#else
 
644
   BOTAN_UNUSED(key, scalar, curve_name);
 
645
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
646
#endif
 
647
   }
 
648
 
 
649
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
 
650
                              const botan_mp_t public_x,
 
651
                              const botan_mp_t public_y,
 
652
                              const char* curve_name)
 
653
   {
 
654
#if defined(BOTAN_HAS_SM2)
 
655
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
656
      std::unique_ptr<Botan::SM2_Encryption_PublicKey> p_key;
 
657
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name))
 
658
         {
 
659
         *key = new botan_pubkey_struct(p_key.release());
 
660
         return BOTAN_FFI_SUCCESS;
 
661
         }
 
662
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
 
663
      });
 
664
#else
 
665
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
 
666
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
667
#endif
 
668
   }
 
669
 
 
670
int botan_privkey_load_sm2_enc(botan_privkey_t* key,
 
671
                               const botan_mp_t scalar,
 
672
                               const char* curve_name)
 
673
   {
 
674
#if defined(BOTAN_HAS_SM2)
 
675
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
676
      std::unique_ptr<Botan::SM2_Encryption_PrivateKey> p_key;
 
677
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
 
678
 
 
679
      if(rc == BOTAN_FFI_SUCCESS)
 
680
         *key = new botan_privkey_struct(p_key.release());
 
681
      return rc;
 
682
      });
 
683
#else
 
684
   BOTAN_UNUSED(key, scalar, curve_name);
 
685
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
686
#endif
 
687
   }
 
688
 
 
689
/* Ed25519 specific operations */
 
690
 
 
691
int botan_privkey_load_ed25519(botan_privkey_t* key,
 
692
                               const uint8_t privkey[32])
 
693
   {
 
694
#if defined(BOTAN_HAS_ED25519)
 
695
   *key = nullptr;
 
696
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
697
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
 
698
      *key = new botan_privkey_struct(new Botan::Ed25519_PrivateKey(privkey_vec));
 
699
      return BOTAN_FFI_SUCCESS;
 
700
      });
 
701
#else
 
702
   BOTAN_UNUSED(key, privkey);
 
703
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
704
#endif
 
705
   }
 
706
 
 
707
int botan_pubkey_load_ed25519(botan_pubkey_t* key,
 
708
                              const uint8_t pubkey[32])
 
709
   {
 
710
#if defined(BOTAN_HAS_ED25519)
 
711
   *key = nullptr;
 
712
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
713
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
 
714
      *key = new botan_pubkey_struct(new Botan::Ed25519_PublicKey(pubkey_vec));
 
715
      return BOTAN_FFI_SUCCESS;
 
716
      });
 
717
#else
 
718
   BOTAN_UNUSED(key, pubkey);
 
719
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
720
#endif
 
721
   }
 
722
 
 
723
int botan_privkey_ed25519_get_privkey(botan_privkey_t key,
 
724
                                      uint8_t output[64])
 
725
   {
 
726
#if defined(BOTAN_HAS_ED25519)
 
727
   return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
 
728
      if(Botan::Ed25519_PrivateKey* ed = dynamic_cast<Botan::Ed25519_PrivateKey*>(&k))
 
729
         {
 
730
         const Botan::secure_vector<uint8_t>& ed_key = ed->get_private_key();
 
731
         if(ed_key.size() != 64)
 
732
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
 
733
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
 
734
         return BOTAN_FFI_SUCCESS;
 
735
         }
 
736
      else
 
737
         {
 
738
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
 
739
         }
 
740
      });
 
741
#else
 
742
   BOTAN_UNUSED(key, output);
 
743
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
744
#endif
 
745
   }
 
746
 
 
747
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key,
 
748
                                    uint8_t output[32])
 
749
   {
 
750
#if defined(BOTAN_HAS_ED25519)
 
751
   return BOTAN_FFI_DO(Botan::Public_Key, key, k, {
 
752
      if(Botan::Ed25519_PublicKey* ed = dynamic_cast<Botan::Ed25519_PublicKey*>(&k))
 
753
         {
 
754
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
 
755
         if(ed_key.size() != 32)
 
756
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
 
757
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
 
758
         return BOTAN_FFI_SUCCESS;
 
759
         }
 
760
      else
 
761
         {
 
762
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
 
763
         }
 
764
      });
 
765
#else
 
766
   BOTAN_UNUSED(key, output);
 
767
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
768
#endif
 
769
   }
 
770
 
 
771
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t)
 
772
   {
 
773
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
 
774
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
 
775
   }
 
776
 
 
777
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
 
778
                         const char* aead,
 
779
                         const uint8_t ct[], size_t ct_len,
 
780
                         const uint8_t ad[], size_t ad_len,
 
781
                         uint8_t out[], size_t* out_len)
 
782
   {
 
783
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
784
      Botan::Private_Key& key = safe_get(mce_key_obj);
 
785
 
 
786
#if defined(BOTAN_HAS_MCELIECE) && defined(BOTAN_HAS_MCEIES)
 
787
      Botan::McEliece_PrivateKey* mce = dynamic_cast<Botan::McEliece_PrivateKey*>(&key);
 
788
      if(!mce)
 
789
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
 
790
 
 
791
      const Botan::secure_vector<uint8_t> pt = mceies_decrypt(*mce, ct, ct_len, ad, ad_len, aead);
 
792
      return write_vec_output(out, out_len, pt);
 
793
#else
 
794
      return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
795
#endif
 
796
      });
 
797
   }
 
798
 
 
799
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
 
800
                         botan_rng_t rng_obj,
 
801
                         const char* aead,
 
802
                         const uint8_t pt[], size_t pt_len,
 
803
                         const uint8_t ad[], size_t ad_len,
 
804
                         uint8_t out[], size_t* out_len)
 
805
   {
 
806
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int {
 
807
      Botan::Public_Key& key = safe_get(mce_key_obj);
 
808
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
 
809
 
 
810
#if defined(BOTAN_HAS_MCELIECE) && defined(BOTAN_HAS_MCEIES)
 
811
      Botan::McEliece_PublicKey* mce = dynamic_cast<Botan::McEliece_PublicKey*>(&key);
 
812
      if(!mce)
 
813
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
 
814
 
 
815
      Botan::secure_vector<uint8_t> ct = mceies_encrypt(*mce, pt, pt_len, ad, ad_len, rng, aead);
 
816
      return write_vec_output(out, out_len, ct);
 
817
#else
 
818
      return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
 
819
#endif
 
820
      });
 
821
   }
 
822
 
 
823
}