Coverage Report

Created: 2025-08-25 06:58

/src/Botan-3.4.0/src/lib/ffi/ffi_pkey_algs.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* (C) 2015,2017 Jack Lloyd
3
* (C) 2017 Ribose Inc
4
* (C) 2018 René Korthaus, Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#include <botan/ffi.h>
10
11
#include <botan/hash.h>
12
#include <botan/pem.h>
13
#include <botan/internal/ffi_mp.h>
14
#include <botan/internal/ffi_pkey.h>
15
#include <botan/internal/ffi_rng.h>
16
#include <botan/internal/ffi_util.h>
17
18
#if defined(BOTAN_HAS_DL_GROUP)
19
   #include <botan/dl_group.h>
20
#endif
21
22
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
23
   #include <botan/ecc_key.h>
24
#endif
25
26
#if defined(BOTAN_HAS_RSA)
27
   #include <botan/rsa.h>
28
#endif
29
30
#if defined(BOTAN_HAS_ELGAMAL)
31
   #include <botan/elgamal.h>
32
#endif
33
34
#if defined(BOTAN_HAS_DSA)
35
   #include <botan/dsa.h>
36
#endif
37
38
#if defined(BOTAN_HAS_ECDSA)
39
   #include <botan/ecdsa.h>
40
#endif
41
42
#if defined(BOTAN_HAS_SM2)
43
   #include <botan/sm2.h>
44
#endif
45
46
#if defined(BOTAN_HAS_ECDH)
47
   #include <botan/ecdh.h>
48
#endif
49
50
#if defined(BOTAN_HAS_CURVE_25519)
51
   #include <botan/curve25519.h>
52
#endif
53
54
#if defined(BOTAN_HAS_X448)
55
   #include <botan/x448.h>
56
#endif
57
58
#if defined(BOTAN_HAS_ED25519)
59
   #include <botan/ed25519.h>
60
#endif
61
62
#if defined(BOTAN_HAS_ED448)
63
   #include <botan/ed448.h>
64
#endif
65
66
#if defined(BOTAN_HAS_MCELIECE)
67
   #include <botan/mceliece.h>
68
#endif
69
70
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
71
   #include <botan/dh.h>
72
#endif
73
74
#if defined(BOTAN_HAS_KYBER)
75
   #include <botan/kyber.h>
76
#endif
77
78
namespace {
79
80
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
81
82
// These are always called within an existing try/catch block
83
84
template <class ECPrivateKey_t>
85
0
int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& scalar, const char* curve_name) {
86
0
   if(curve_name == nullptr) {
87
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
88
0
   }
89
90
0
   Botan::Null_RNG null_rng;
91
0
   Botan::EC_Group grp(curve_name);
92
0
   key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
93
0
   return BOTAN_FFI_SUCCESS;
94
0
}
Unexecuted instantiation: ffi_pkey_algs.cpp:int (anonymous namespace)::privkey_load_ec<Botan::ECDSA_PrivateKey>(std::__1::unique_ptr<Botan::ECDSA_PrivateKey, std::__1::default_delete<Botan::ECDSA_PrivateKey> >&, Botan::BigInt const&, char const*)
Unexecuted instantiation: ffi_pkey_algs.cpp:int (anonymous namespace)::privkey_load_ec<Botan::ECDH_PrivateKey>(std::__1::unique_ptr<Botan::ECDH_PrivateKey, std::__1::default_delete<Botan::ECDH_PrivateKey> >&, Botan::BigInt const&, char const*)
Unexecuted instantiation: ffi_pkey_algs.cpp:int (anonymous namespace)::privkey_load_ec<Botan::SM2_PrivateKey>(std::__1::unique_ptr<Botan::SM2_PrivateKey, std::__1::default_delete<Botan::SM2_PrivateKey> >&, Botan::BigInt const&, char const*)
95
96
template <class ECPublicKey_t>
97
int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
98
                   const Botan::BigInt& public_x,
99
                   const Botan::BigInt& public_y,
100
69.8k
                   const char* curve_name) {
101
69.8k
   if(curve_name == nullptr) {
102
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
103
0
   }
104
105
69.8k
   Botan::EC_Group grp(curve_name);
106
69.8k
   Botan::EC_Point uncompressed_point = grp.point(public_x, public_y);
107
69.8k
   key.reset(new ECPublicKey_t(grp, uncompressed_point));
108
69.8k
   return BOTAN_FFI_SUCCESS;
109
69.8k
}
ffi_pkey_algs.cpp:int (anonymous namespace)::pubkey_load_ec<Botan::ECDSA_PublicKey>(std::__1::unique_ptr<Botan::ECDSA_PublicKey, std::__1::default_delete<Botan::ECDSA_PublicKey> >&, Botan::BigInt const&, Botan::BigInt const&, char const*)
Line
Count
Source
100
54.9k
                   const char* curve_name) {
101
54.9k
   if(curve_name == nullptr) {
102
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
103
0
   }
104
105
54.9k
   Botan::EC_Group grp(curve_name);
106
54.9k
   Botan::EC_Point uncompressed_point = grp.point(public_x, public_y);
107
54.9k
   key.reset(new ECPublicKey_t(grp, uncompressed_point));
108
54.9k
   return BOTAN_FFI_SUCCESS;
109
54.9k
}
Unexecuted instantiation: ffi_pkey_algs.cpp:int (anonymous namespace)::pubkey_load_ec<Botan::ECDH_PublicKey>(std::__1::unique_ptr<Botan::ECDH_PublicKey, std::__1::default_delete<Botan::ECDH_PublicKey> >&, Botan::BigInt const&, Botan::BigInt const&, char const*)
ffi_pkey_algs.cpp:int (anonymous namespace)::pubkey_load_ec<Botan::SM2_PublicKey>(std::__1::unique_ptr<Botan::SM2_PublicKey, std::__1::default_delete<Botan::SM2_PublicKey> >&, Botan::BigInt const&, Botan::BigInt const&, char const*)
Line
Count
Source
100
14.9k
                   const char* curve_name) {
101
14.9k
   if(curve_name == nullptr) {
102
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
103
0
   }
104
105
14.9k
   Botan::EC_Group grp(curve_name);
106
14.9k
   Botan::EC_Point uncompressed_point = grp.point(public_x, public_y);
107
14.9k
   key.reset(new ECPublicKey_t(grp, uncompressed_point));
108
14.9k
   return BOTAN_FFI_SUCCESS;
109
14.9k
}
110
111
#endif
112
113
0
Botan::BigInt pubkey_get_field(const Botan::Public_Key& key, std::string_view field) {
114
0
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
115
   // Not currently handled by get_int_field
116
0
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
117
0
      if(field == "public_x") {
118
0
         return ecc->public_point().get_affine_x();
119
0
      } else if(field == "public_y") {
120
0
         return ecc->public_point().get_affine_y();
121
0
      }
122
0
   }
123
0
#endif
124
125
0
   try {
126
0
      return key.get_int_field(field);
127
0
   } catch(Botan::Unknown_PK_Field_Name&) {
128
0
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
129
0
   }
130
0
}
131
132
0
Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
133
0
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
134
   // Not currently handled by get_int_field
135
0
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
136
0
      if(field == "public_x") {
137
0
         return ecc->public_point().get_affine_x();
138
0
      } else if(field == "public_y") {
139
0
         return ecc->public_point().get_affine_y();
140
0
      }
141
0
   }
142
0
#endif
143
144
0
   try {
145
0
      return key.get_int_field(field);
146
0
   } catch(Botan::Unknown_PK_Field_Name&) {
147
0
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
148
0
   }
149
0
}
150
151
}  // namespace
152
153
extern "C" {
154
155
using namespace Botan_FFI;
156
157
0
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
158
0
   if(field_name_cstr == nullptr) {
159
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
160
0
   }
161
162
0
   const std::string field_name(field_name_cstr);
163
164
0
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
165
0
}
166
167
0
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
168
0
   if(field_name_cstr == nullptr) {
169
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
170
0
   }
171
172
0
   const std::string field_name(field_name_cstr);
173
174
0
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
175
0
}
176
177
/* RSA specific operations */
178
179
0
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
180
0
   if(n_bits < 1024 || n_bits > 16 * 1024) {
181
0
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
182
0
   }
183
184
0
   std::string n_str = std::to_string(n_bits);
185
186
0
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
187
0
}
188
189
0
int botan_privkey_load_rsa(botan_privkey_t* key, botan_mp_t rsa_p, botan_mp_t rsa_q, botan_mp_t rsa_e) {
190
0
#if defined(BOTAN_HAS_RSA)
191
0
   *key = nullptr;
192
193
0
   return ffi_guard_thunk(__func__, [=]() -> int {
194
0
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
195
0
      *key = new botan_privkey_struct(std::move(rsa));
196
0
      return BOTAN_FFI_SUCCESS;
197
0
   });
198
#else
199
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
200
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
201
#endif
202
0
}
203
204
0
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
205
0
#if defined(BOTAN_HAS_RSA)
206
0
   *key = nullptr;
207
208
0
   Botan::secure_vector<uint8_t> src(bits, bits + len);
209
0
   return ffi_guard_thunk(__func__, [=]() -> int {
210
0
      Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
211
0
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
212
0
      *key = new botan_privkey_struct(std::move(rsa));
213
0
      return BOTAN_FFI_SUCCESS;
214
0
   });
215
#else
216
   BOTAN_UNUSED(key, bits, len);
217
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
218
#endif
219
0
}
220
221
54.8k
int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e) {
222
54.8k
#if defined(BOTAN_HAS_RSA)
223
54.8k
   *key = nullptr;
224
54.8k
   return ffi_guard_thunk(__func__, [=]() -> int {
225
54.8k
      auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
226
54.8k
      *key = new botan_pubkey_struct(std::move(rsa));
227
54.8k
      return BOTAN_FFI_SUCCESS;
228
54.8k
   });
229
#else
230
   BOTAN_UNUSED(key, n, e);
231
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
232
#endif
233
54.8k
}
234
235
0
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) {
236
0
   return botan_privkey_get_field(p, key, "p");
237
0
}
238
239
0
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) {
240
0
   return botan_privkey_get_field(q, key, "q");
241
0
}
242
243
0
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) {
244
0
   return botan_privkey_get_field(n, key, "n");
245
0
}
246
247
0
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
248
0
   return botan_privkey_get_field(e, key, "e");
249
0
}
250
251
0
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
252
0
   return botan_privkey_get_field(d, key, "d");
253
0
}
254
255
0
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
256
0
   return botan_pubkey_get_field(e, key, "e");
257
0
}
258
259
0
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
260
0
   return botan_pubkey_get_field(n, key, "n");
261
0
}
262
263
0
int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
264
0
#if defined(BOTAN_HAS_RSA)
265
0
   return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
266
0
      if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
267
0
         if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
268
0
            return write_vec_output(out, out_len, rsa->private_key_bits());
269
0
         else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
270
0
            return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
271
0
         else
272
0
            return BOTAN_FFI_ERROR_BAD_FLAG;
273
0
      } else {
274
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
275
0
      }
276
0
   });
277
#else
278
   BOTAN_UNUSED(rsa_key, out, out_len, flags);
279
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
280
#endif
281
0
}
282
283
/* DSA specific operations */
284
0
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
285
0
#if defined(BOTAN_HAS_DSA)
286
287
0
   if((rng_obj == nullptr) || (key == nullptr)) {
288
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
289
0
   }
290
291
0
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
292
0
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
293
0
   }
294
295
0
   return ffi_guard_thunk(__func__, [=]() -> int {
296
0
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
297
0
      Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
298
0
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
299
0
      *key = new botan_privkey_struct(std::move(dsa));
300
0
      return BOTAN_FFI_SUCCESS;
301
0
   });
302
#else
303
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
304
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
305
#endif
306
0
}
307
308
0
int botan_privkey_load_dsa(botan_privkey_t* key, botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t x) {
309
0
#if defined(BOTAN_HAS_DSA)
310
0
   *key = nullptr;
311
312
0
   return ffi_guard_thunk(__func__, [=]() -> int {
313
0
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
314
0
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
315
0
      *key = new botan_privkey_struct(std::move(dsa));
316
0
      return BOTAN_FFI_SUCCESS;
317
0
   });
318
#else
319
   BOTAN_UNUSED(key, p, q, g, x);
320
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
321
#endif
322
0
}
323
324
14.1k
int botan_pubkey_load_dsa(botan_pubkey_t* key, botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t y) {
325
14.1k
#if defined(BOTAN_HAS_DSA)
326
14.1k
   *key = nullptr;
327
328
14.1k
   return ffi_guard_thunk(__func__, [=]() -> int {
329
14.1k
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
330
14.1k
      auto dsa = std::make_unique<Botan::DSA_PublicKey>(group, safe_get(y));
331
14.1k
      *key = new botan_pubkey_struct(std::move(dsa));
332
14.1k
      return BOTAN_FFI_SUCCESS;
333
14.1k
   });
334
#else
335
   BOTAN_UNUSED(key, p, q, g, y);
336
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
337
#endif
338
14.1k
}
339
340
0
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
341
0
   return botan_privkey_get_field(x, key, "x");
342
0
}
343
344
0
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
345
0
   return botan_pubkey_get_field(p, key, "p");
346
0
}
347
348
0
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) {
349
0
   return botan_pubkey_get_field(q, key, "q");
350
0
}
351
352
0
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
353
0
   return botan_pubkey_get_field(g, key, "g");
354
0
}
355
356
0
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
357
0
   return botan_pubkey_get_field(y, key, "y");
358
0
}
359
360
0
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
361
0
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
362
0
}
363
364
/* ECDSA specific operations */
365
366
0
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key) {
367
0
#if defined(BOTAN_HAS_ECC_KEY)
368
0
   return ffi_guard_thunk(__func__, [=]() -> int {
369
0
      const Botan::Public_Key& pub_key = safe_get(key);
370
0
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
371
372
0
      if(ec_key == nullptr) {
373
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
374
0
      }
375
376
0
      return ec_key->domain().used_explicit_encoding() ? 1 : 0;
377
0
   });
378
#else
379
   BOTAN_UNUSED(key);
380
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
381
#endif
382
0
}
383
384
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
385
                            const botan_mp_t public_x,
386
                            const botan_mp_t public_y,
387
54.9k
                            const char* curve_name) {
388
54.9k
#if defined(BOTAN_HAS_ECDSA)
389
54.9k
   return ffi_guard_thunk(__func__, [=]() -> int {
390
54.9k
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
391
392
54.9k
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
393
54.9k
      if(rc == BOTAN_FFI_SUCCESS) {
394
54.8k
         *key = new botan_pubkey_struct(std::move(p_key));
395
54.8k
      }
396
397
54.9k
      return rc;
398
54.9k
   });
399
#else
400
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
401
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
402
#endif
403
54.9k
}
404
405
0
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
406
0
#if defined(BOTAN_HAS_ECDSA)
407
0
   return ffi_guard_thunk(__func__, [=]() -> int {
408
0
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
409
0
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
410
0
      if(rc == BOTAN_FFI_SUCCESS) {
411
0
         *key = new botan_privkey_struct(std::move(p_key));
412
0
      }
413
0
      return rc;
414
0
   });
415
#else
416
   BOTAN_UNUSED(key, scalar, curve_name);
417
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
418
#endif
419
0
}
420
421
/* ElGamal specific operations */
422
0
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
423
0
#if defined(BOTAN_HAS_ELGAMAL)
424
425
0
   if((rng_obj == nullptr) || (key == nullptr)) {
426
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
427
0
   }
428
429
0
   if((pbits < 1024) || (qbits < 160)) {
430
0
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
431
0
   }
432
433
0
   Botan::DL_Group::PrimeType prime_type =
434
0
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
435
436
0
   return ffi_guard_thunk(__func__, [=]() -> int {
437
0
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
438
0
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
439
0
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
440
0
      *key = new botan_privkey_struct(std::move(elg));
441
0
      return BOTAN_FFI_SUCCESS;
442
0
   });
443
#else
444
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
445
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
446
#endif
447
0
}
448
449
0
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
450
0
#if defined(BOTAN_HAS_ELGAMAL)
451
0
   *key = nullptr;
452
0
   return ffi_guard_thunk(__func__, [=]() -> int {
453
0
      Botan::DL_Group group(safe_get(p), safe_get(g));
454
0
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
455
0
      *key = new botan_pubkey_struct(std::move(elg));
456
0
      return BOTAN_FFI_SUCCESS;
457
0
   });
458
#else
459
   BOTAN_UNUSED(key, p, g, y);
460
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
461
#endif
462
0
}
463
464
0
int botan_privkey_load_elgamal(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
465
0
#if defined(BOTAN_HAS_ELGAMAL)
466
0
   *key = nullptr;
467
0
   return ffi_guard_thunk(__func__, [=]() -> int {
468
0
      Botan::DL_Group group(safe_get(p), safe_get(g));
469
0
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(group, safe_get(x));
470
0
      *key = new botan_privkey_struct(std::move(elg));
471
0
      return BOTAN_FFI_SUCCESS;
472
0
   });
473
#else
474
   BOTAN_UNUSED(key, p, g, x);
475
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
476
#endif
477
0
}
478
479
/* Diffie Hellman specific operations */
480
481
0
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
482
0
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
483
0
}
484
485
0
int botan_privkey_load_dh(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
486
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
487
   *key = nullptr;
488
   return ffi_guard_thunk(__func__, [=]() -> int {
489
      Botan::DL_Group group(safe_get(p), safe_get(g));
490
      auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
491
      *key = new botan_privkey_struct(std::move(dh));
492
      return BOTAN_FFI_SUCCESS;
493
   });
494
#else
495
0
   BOTAN_UNUSED(key, p, g, x);
496
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
497
0
#endif
498
0
}
499
500
0
int botan_pubkey_load_dh(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
501
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
502
   *key = nullptr;
503
   return ffi_guard_thunk(__func__, [=]() -> int {
504
      Botan::DL_Group group(safe_get(p), safe_get(g));
505
      auto dh = std::make_unique<Botan::DH_PublicKey>(group, safe_get(y));
506
      *key = new botan_pubkey_struct(std::move(dh));
507
      return BOTAN_FFI_SUCCESS;
508
   });
509
#else
510
0
   BOTAN_UNUSED(key, p, g, y);
511
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
512
0
#endif
513
0
}
514
515
/* ECDH + x25519/x448 specific operations */
516
517
0
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
518
0
   if(param_str == nullptr) {
519
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
520
0
   }
521
522
0
   const std::string params(param_str);
523
524
0
   if(params == "curve25519") {
525
0
      return botan_privkey_create(key_obj, "Curve25519", "", rng_obj);
526
0
   }
527
528
0
   if(params == "x448") {
529
0
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
530
0
   }
531
532
0
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
533
0
}
534
535
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
536
                           const botan_mp_t public_x,
537
                           const botan_mp_t public_y,
538
0
                           const char* curve_name) {
539
0
#if defined(BOTAN_HAS_ECDH)
540
0
   return ffi_guard_thunk(__func__, [=]() -> int {
541
0
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
542
0
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
543
544
0
      if(rc == BOTAN_FFI_SUCCESS) {
545
0
         *key = new botan_pubkey_struct(std::move(p_key));
546
0
      }
547
0
      return rc;
548
0
   });
549
#else
550
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
551
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
552
#endif
553
0
}
554
555
0
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
556
0
#if defined(BOTAN_HAS_ECDH)
557
0
   return ffi_guard_thunk(__func__, [=]() -> int {
558
0
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
559
0
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
560
0
      if(rc == BOTAN_FFI_SUCCESS) {
561
0
         *key = new botan_privkey_struct(std::move(p_key));
562
0
      }
563
0
      return rc;
564
0
   });
565
#else
566
   BOTAN_UNUSED(key, scalar, curve_name);
567
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
568
#endif
569
0
}
570
571
/* SM2 specific operations */
572
573
int botan_pubkey_sm2_compute_za(
574
7.58k
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
575
7.58k
   if(out == nullptr || out_len == nullptr) {
576
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
577
0
   }
578
7.58k
   if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
579
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
580
0
   }
581
582
7.58k
#if defined(BOTAN_HAS_SM2)
583
7.58k
   return ffi_guard_thunk(__func__, [=]() -> int {
584
7.58k
      const Botan::Public_Key& pub_key = safe_get(key);
585
7.58k
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
586
587
7.58k
      if(ec_key == nullptr) {
588
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
589
0
      }
590
591
7.58k
      if(ec_key->algo_name() != "SM2") {
592
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
593
0
      }
594
595
7.58k
      const std::string ident_str(ident);
596
7.58k
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
597
598
7.58k
      const std::vector<uint8_t> za = Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), ec_key->public_point());
599
600
7.58k
      return write_vec_output(out, out_len, za);
601
7.58k
   });
602
#else
603
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
604
#endif
605
7.58k
}
606
607
int botan_pubkey_load_sm2(botan_pubkey_t* key,
608
                          const botan_mp_t public_x,
609
                          const botan_mp_t public_y,
610
14.9k
                          const char* curve_name) {
611
14.9k
#if defined(BOTAN_HAS_SM2)
612
14.9k
   return ffi_guard_thunk(__func__, [=]() -> int {
613
14.9k
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
614
14.9k
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
615
14.8k
         *key = new botan_pubkey_struct(std::move(p_key));
616
14.8k
         return BOTAN_FFI_SUCCESS;
617
14.8k
      }
618
111
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
619
14.9k
   });
620
#else
621
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
622
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
623
#endif
624
14.9k
}
625
626
0
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
627
0
#if defined(BOTAN_HAS_SM2)
628
0
   return ffi_guard_thunk(__func__, [=]() -> int {
629
0
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
630
0
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
631
632
0
      if(rc == BOTAN_FFI_SUCCESS) {
633
0
         *key = new botan_privkey_struct(std::move(p_key));
634
0
      }
635
0
      return rc;
636
0
   });
637
#else
638
   BOTAN_UNUSED(key, scalar, curve_name);
639
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
640
#endif
641
0
}
642
643
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
644
                              const botan_mp_t public_x,
645
                              const botan_mp_t public_y,
646
0
                              const char* curve_name) {
647
0
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
648
0
}
649
650
0
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
651
0
   return botan_privkey_load_sm2(key, scalar, curve_name);
652
0
}
653
654
/* Ed25519 specific operations */
655
656
0
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
657
0
#if defined(BOTAN_HAS_ED25519)
658
0
   *key = nullptr;
659
0
   return ffi_guard_thunk(__func__, [=]() -> int {
660
0
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
661
0
      auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
662
0
      *key = new botan_privkey_struct(std::move(ed25519));
663
0
      return BOTAN_FFI_SUCCESS;
664
0
   });
665
#else
666
   BOTAN_UNUSED(key, privkey);
667
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
668
#endif
669
0
}
670
671
64.6k
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
672
64.6k
#if defined(BOTAN_HAS_ED25519)
673
64.6k
   *key = nullptr;
674
64.6k
   return ffi_guard_thunk(__func__, [=]() -> int {
675
64.6k
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
676
64.6k
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
677
64.6k
      *key = new botan_pubkey_struct(std::move(ed25519));
678
64.6k
      return BOTAN_FFI_SUCCESS;
679
64.6k
   });
680
#else
681
   BOTAN_UNUSED(key, pubkey);
682
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
683
#endif
684
64.6k
}
685
686
0
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
687
0
#if defined(BOTAN_HAS_ED25519)
688
0
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
689
0
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
690
0
         const auto ed_key = ed->raw_private_key_bits();
691
0
         if(ed_key.size() != 64)
692
0
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
693
0
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
694
0
         return BOTAN_FFI_SUCCESS;
695
0
      } else {
696
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
697
0
      }
698
0
   });
699
#else
700
   BOTAN_UNUSED(key, output);
701
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
702
#endif
703
0
}
704
705
0
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
706
0
#if defined(BOTAN_HAS_ED25519)
707
0
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
708
0
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
709
0
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
710
0
         if(ed_key.size() != 32)
711
0
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
712
0
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
713
0
         return BOTAN_FFI_SUCCESS;
714
0
      } else {
715
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
716
0
      }
717
0
   });
718
#else
719
   BOTAN_UNUSED(key, output);
720
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
721
#endif
722
0
}
723
724
/* Ed448 specific operations */
725
726
0
int botan_privkey_load_ed448(botan_privkey_t* key, const uint8_t privkey[57]) {
727
#if defined(BOTAN_HAS_ED448)
728
   *key = nullptr;
729
   return ffi_guard_thunk(__func__, [=]() -> int {
730
      auto ed448 = std::make_unique<Botan::Ed448_PrivateKey>(std::span(privkey, 57));
731
      *key = new botan_privkey_struct(std::move(ed448));
732
      return BOTAN_FFI_SUCCESS;
733
   });
734
#else
735
0
   BOTAN_UNUSED(key, privkey);
736
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
737
0
#endif
738
0
}
739
740
0
int botan_pubkey_load_ed448(botan_pubkey_t* key, const uint8_t pubkey[57]) {
741
#if defined(BOTAN_HAS_ED448)
742
   *key = nullptr;
743
   return ffi_guard_thunk(__func__, [=]() -> int {
744
      auto ed448 = std::make_unique<Botan::Ed448_PublicKey>(std::span(pubkey, 57));
745
      *key = new botan_pubkey_struct(std::move(ed448));
746
      return BOTAN_FFI_SUCCESS;
747
   });
748
#else
749
0
   BOTAN_UNUSED(key, pubkey);
750
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
751
0
#endif
752
0
}
753
754
0
int botan_privkey_ed448_get_privkey(botan_privkey_t key, uint8_t output[57]) {
755
#if defined(BOTAN_HAS_ED448)
756
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
757
      if(auto ed = dynamic_cast<const Botan::Ed448_PrivateKey*>(&k)) {
758
         const auto ed_key = ed->raw_private_key_bits();
759
         Botan::copy_mem(std::span(output, 57), ed_key);
760
         return BOTAN_FFI_SUCCESS;
761
      } else {
762
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
763
      }
764
   });
765
#else
766
0
   BOTAN_UNUSED(key, output);
767
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
768
0
#endif
769
0
}
770
771
0
int botan_pubkey_ed448_get_pubkey(botan_pubkey_t key, uint8_t output[57]) {
772
#if defined(BOTAN_HAS_ED448)
773
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
774
      if(auto ed = dynamic_cast<const Botan::Ed448_PublicKey*>(&k)) {
775
         const auto ed_key = ed->public_key_bits();
776
         Botan::copy_mem(std::span(output, 57), ed_key);
777
         return BOTAN_FFI_SUCCESS;
778
      } else {
779
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
780
      }
781
   });
782
#else
783
0
   BOTAN_UNUSED(key, output);
784
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
785
0
#endif
786
0
}
787
788
/* X25519 specific operations */
789
790
0
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
791
0
#if defined(BOTAN_HAS_X25519)
792
0
   *key = nullptr;
793
0
   return ffi_guard_thunk(__func__, [=]() -> int {
794
0
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
795
0
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
796
0
      *key = new botan_privkey_struct(std::move(x25519));
797
0
      return BOTAN_FFI_SUCCESS;
798
0
   });
799
#else
800
   BOTAN_UNUSED(key, privkey);
801
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
802
#endif
803
0
}
804
805
0
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
806
0
#if defined(BOTAN_HAS_X25519)
807
0
   *key = nullptr;
808
0
   return ffi_guard_thunk(__func__, [=]() -> int {
809
0
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
810
0
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(pubkey_vec);
811
0
      *key = new botan_pubkey_struct(std::move(x25519));
812
0
      return BOTAN_FFI_SUCCESS;
813
0
   });
814
#else
815
   BOTAN_UNUSED(key, pubkey);
816
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
817
#endif
818
0
}
819
820
0
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
821
0
#if defined(BOTAN_HAS_X25519)
822
0
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
823
0
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
824
0
         const auto x25519_key = x25519->raw_private_key_bits();
825
0
         if(x25519_key.size() != 32)
826
0
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
827
0
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
828
0
         return BOTAN_FFI_SUCCESS;
829
0
      } else {
830
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
831
0
      }
832
0
   });
833
#else
834
   BOTAN_UNUSED(key, output);
835
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
836
#endif
837
0
}
838
839
0
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
840
0
#if defined(BOTAN_HAS_X25519)
841
0
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
842
0
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
843
0
         const std::vector<uint8_t>& x25519_key = x25519->public_value();
844
0
         if(x25519_key.size() != 32)
845
0
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
846
0
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
847
0
         return BOTAN_FFI_SUCCESS;
848
0
      } else {
849
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
850
0
      }
851
0
   });
852
#else
853
   BOTAN_UNUSED(key, output);
854
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
855
#endif
856
0
}
857
858
/* X448 specific operations */
859
860
0
int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
861
#if defined(BOTAN_HAS_X448)
862
   *key = nullptr;
863
   return ffi_guard_thunk(__func__, [=]() -> int {
864
      auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span(privkey, 56));
865
      *key = new botan_privkey_struct(std::move(x448));
866
      return BOTAN_FFI_SUCCESS;
867
   });
868
#else
869
0
   BOTAN_UNUSED(key, privkey);
870
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
871
0
#endif
872
0
}
873
874
0
int botan_pubkey_load_x448(botan_pubkey_t* key, const uint8_t pubkey[56]) {
875
#if defined(BOTAN_HAS_X448)
876
   *key = nullptr;
877
   return ffi_guard_thunk(__func__, [=]() -> int {
878
      auto x448 = std::make_unique<Botan::X448_PublicKey>(std::span(pubkey, 56));
879
      *key = new botan_pubkey_struct(std::move(x448));
880
      return BOTAN_FFI_SUCCESS;
881
   });
882
#else
883
0
   BOTAN_UNUSED(key, pubkey);
884
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
885
0
#endif
886
0
}
887
888
0
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56]) {
889
#if defined(BOTAN_HAS_X448)
890
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
891
      if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
892
         const auto x448_key = x448->raw_private_key_bits();
893
         Botan::copy_mem(std::span(output, 56), x448_key);
894
         return BOTAN_FFI_SUCCESS;
895
      } else {
896
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
897
      }
898
   });
899
#else
900
0
   BOTAN_UNUSED(key, output);
901
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
902
0
#endif
903
0
}
904
905
0
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
906
#if defined(BOTAN_HAS_X448)
907
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
908
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
909
         const std::vector<uint8_t>& x448_key = x448->public_value();
910
         Botan::copy_mem(std::span(output, 56), x448_key);
911
         return BOTAN_FFI_SUCCESS;
912
      } else {
913
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
914
      }
915
   });
916
#else
917
0
   BOTAN_UNUSED(key, output);
918
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
919
0
#endif
920
0
}
921
922
/*
923
* Algorithm specific key operations: Kyber
924
*/
925
926
0
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
927
0
#if defined(BOTAN_HAS_KYBER)
928
0
   *key = nullptr;
929
0
   switch(key_len) {
930
0
      case 1632:
931
0
         return ffi_guard_thunk(__func__, [=]() -> int {
932
0
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 1632);
933
0
            auto kyber512 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber512_R3);
934
0
            *key = new botan_privkey_struct(std::move(kyber512));
935
0
            return BOTAN_FFI_SUCCESS;
936
0
         });
937
0
      case 2400:
938
0
         return ffi_guard_thunk(__func__, [=]() -> int {
939
0
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
940
0
            auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768_R3);
941
0
            *key = new botan_privkey_struct(std::move(kyber768));
942
0
            return BOTAN_FFI_SUCCESS;
943
0
         });
944
0
      case 3168:
945
0
         return ffi_guard_thunk(__func__, [=]() -> int {
946
0
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 3168);
947
0
            auto kyber1024 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber1024_R3);
948
0
            *key = new botan_privkey_struct(std::move(kyber1024));
949
0
            return BOTAN_FFI_SUCCESS;
950
0
         });
951
0
      default:
952
0
         BOTAN_UNUSED(key, privkey, key_len);
953
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
954
0
   }
955
#else
956
   BOTAN_UNUSED(key, privkey);
957
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
958
#endif
959
0
}
960
961
0
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
962
0
#if defined(BOTAN_HAS_KYBER)
963
0
   *key = nullptr;
964
0
   switch(key_len) {
965
0
      case 800:
966
0
         return ffi_guard_thunk(__func__, [=]() -> int {
967
0
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 800);
968
0
            auto kyber512 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber512_R3);
969
0
            *key = new botan_pubkey_struct(std::move(kyber512));
970
0
            return BOTAN_FFI_SUCCESS;
971
0
         });
972
0
      case 1184:
973
0
         return ffi_guard_thunk(__func__, [=]() -> int {
974
0
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
975
0
            auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768_R3);
976
0
            *key = new botan_pubkey_struct(std::move(kyber768));
977
0
            return BOTAN_FFI_SUCCESS;
978
0
         });
979
0
      case 1568:
980
0
         return ffi_guard_thunk(__func__, [=]() -> int {
981
0
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1568);
982
0
            auto kyber1024 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber1024_R3);
983
0
            *key = new botan_pubkey_struct(std::move(kyber1024));
984
0
            return BOTAN_FFI_SUCCESS;
985
0
         });
986
0
      default:
987
0
         BOTAN_UNUSED(key, pubkey, key_len);
988
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
989
0
   }
990
#else
991
   BOTAN_UNUSED(key, pubkey, key_len);
992
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
993
#endif
994
0
}
995
996
0
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
997
0
#if defined(BOTAN_HAS_KYBER)
998
0
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
999
0
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1000
0
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1001
0
      } else {
1002
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1003
0
      }
1004
0
   });
1005
#else
1006
   BOTAN_UNUSED(key, ctx, view);
1007
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1008
#endif
1009
0
}
1010
1011
0
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
1012
0
#if defined(BOTAN_HAS_KYBER)
1013
0
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
1014
0
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1015
0
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1016
0
      } else {
1017
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1018
0
      }
1019
0
   });
1020
#else
1021
   BOTAN_UNUSED(key, ctx, view);
1022
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1023
#endif
1024
0
}
1025
1026
0
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
1027
0
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1028
0
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
1029
0
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1030
0
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
1031
0
         return invoke_view_callback(view, ctx, pt);
1032
0
      } else {
1033
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1034
0
      }
1035
0
   });
1036
#else
1037
   BOTAN_UNUSED(key, view, ctx);
1038
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1039
#endif
1040
0
}
1041
1042
0
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1043
0
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
1044
0
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1045
0
}
1046
1047
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
1048
                         const char* aead,
1049
                         const uint8_t ct[],
1050
                         size_t ct_len,
1051
                         const uint8_t ad[],
1052
                         size_t ad_len,
1053
                         uint8_t out[],
1054
0
                         size_t* out_len) {
1055
0
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
1056
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1057
0
}
1058
1059
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
1060
                         botan_rng_t rng_obj,
1061
                         const char* aead,
1062
                         const uint8_t pt[],
1063
                         size_t pt_len,
1064
                         const uint8_t ad[],
1065
                         size_t ad_len,
1066
                         uint8_t out[],
1067
0
                         size_t* out_len) {
1068
0
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
1069
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1070
0
}
1071
}