• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 11950428784

21 Nov 2024 09:33AM UTC coverage: 91.243% (+0.2%) from 91.063%
11950428784

Pull #3883

github

web-flow
Merge c256e1c95 into e5ec40828
Pull Request #3883: PQC: Classic McEliece

93271 of 102223 relevant lines covered (91.24%)

11354227.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.37
/src/lib/ffi/ffi_pkey_algs.cpp
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_X25519)
51
   #include <botan/x25519.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) || defined(BOTAN_HAS_KYBER_90S)
75
   #include <botan/kyber.h>
76
#endif
77

78
#if defined(BOTAN_HAS_ML_KEM)
79
   #include <botan/ml_kem.h>
80
#endif
81

82
#if defined(BOTAN_HAS_FRODOKEM)
83
   #include <botan/frodokem.h>
84
#endif
85

86
#if defined(BOTAN_HAS_ML_DSA)
87
   #include <botan/ml_dsa.h>
88
#endif
89

90
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
91
   #include <botan/slh_dsa.h>
92
#endif
93

94
#if defined(BOTAN_HAS_CLASSICMCELIECE)
95
   #include <botan/cmce.h>
96
#endif
97

98
namespace {
99

100
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
101

102
// These are always called within an existing try/catch block
103

104
template <class ECPrivateKey_t>
105
int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& scalar, const char* curve_name) {
9✔
106
   if(curve_name == nullptr) {
9✔
107
      return BOTAN_FFI_ERROR_NULL_POINTER;
108
   }
109

110
   Botan::Null_RNG null_rng;
9✔
111
   const auto grp = Botan::EC_Group::from_name(curve_name);
9✔
112
   key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
9✔
113
   return BOTAN_FFI_SUCCESS;
114
}
9✔
115

116
template <class ECPublicKey_t>
117
int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
6✔
118
                   const Botan::BigInt& public_x,
119
                   const Botan::BigInt& public_y,
120
                   const char* curve_name) {
121
   if(curve_name == nullptr) {
6✔
122
      return BOTAN_FFI_ERROR_NULL_POINTER;
123
   }
124

125
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
126

127
   if(auto pt = Botan::EC_AffinePoint::from_bigint_xy(group, public_x, public_y)) {
6✔
128
      key.reset(new ECPublicKey_t(group, pt->to_legacy_point()));
6✔
129
      return BOTAN_FFI_SUCCESS;
6✔
130
   } else {
131
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
132
   }
133
}
6✔
134

135
#endif
136

137
Botan::BigInt pubkey_get_field(const Botan::Public_Key& key, std::string_view field) {
40✔
138
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
139
   // Not currently handled by get_int_field
140
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
40✔
141
      if(field == "public_x") {
15✔
142
         return ecc->public_point().get_affine_x();
8✔
143
      } else if(field == "public_y") {
7✔
144
         return ecc->public_point().get_affine_y();
6✔
145
      }
146
   }
147
#endif
148

149
   try {
26✔
150
      return key.get_int_field(field);
26✔
151
   } catch(Botan::Unknown_PK_Field_Name&) {
2✔
152
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
2✔
153
   }
2✔
154
}
155

156
Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
35✔
157
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
158
   // Not currently handled by get_int_field
159
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
35✔
160
      if(field == "public_x") {
16✔
161
         return ecc->public_point().get_affine_x();
2✔
162
      } else if(field == "public_y") {
14✔
163
         return ecc->public_point().get_affine_y();
4✔
164
      }
165
   }
166
#endif
167

168
   try {
29✔
169
      return key.get_int_field(field);
29✔
170
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
171
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
172
   }
4✔
173
}
174

175
}  // namespace
176

177
extern "C" {
178

179
using namespace Botan_FFI;
180

181
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
182
   if(field_name_cstr == nullptr) {
40✔
183
      return BOTAN_FFI_ERROR_NULL_POINTER;
184
   }
185

186
   const std::string field_name(field_name_cstr);
40✔
187

188
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
189
}
40✔
190

191
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
192
   if(field_name_cstr == nullptr) {
35✔
193
      return BOTAN_FFI_ERROR_NULL_POINTER;
194
   }
195

196
   const std::string field_name(field_name_cstr);
35✔
197

198
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
140✔
199
}
35✔
200

201
/* RSA specific operations */
202

203
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
1✔
204
   if(n_bits < 1024 || n_bits > 16 * 1024) {
1✔
205
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
206
   }
207

208
   std::string n_str = std::to_string(n_bits);
1✔
209

210
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
211
}
1✔
212

213
int botan_privkey_load_rsa(botan_privkey_t* key, botan_mp_t rsa_p, botan_mp_t rsa_q, botan_mp_t rsa_e) {
2✔
214
#if defined(BOTAN_HAS_RSA)
215
   *key = nullptr;
2✔
216

217
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
218
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
2✔
219
      *key = new botan_privkey_struct(std::move(rsa));
2✔
220
      return BOTAN_FFI_SUCCESS;
2✔
221
   });
4✔
222
#else
223
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
224
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
225
#endif
226
}
227

228
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
229
#if defined(BOTAN_HAS_RSA)
230
   *key = nullptr;
1✔
231

232
   Botan::secure_vector<uint8_t> src(bits, bits + len);
1✔
233
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
234
      Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
1✔
235
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
1✔
236
      *key = new botan_privkey_struct(std::move(rsa));
1✔
237
      return BOTAN_FFI_SUCCESS;
1✔
238
   });
1✔
239
#else
240
   BOTAN_UNUSED(key, bits, len);
241
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
242
#endif
243
}
1✔
244

245
int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e) {
4✔
246
#if defined(BOTAN_HAS_RSA)
247
   *key = nullptr;
4✔
248
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
249
      auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
4✔
250
      *key = new botan_pubkey_struct(std::move(rsa));
6✔
251
      return BOTAN_FFI_SUCCESS;
3✔
252
   });
7✔
253
#else
254
   BOTAN_UNUSED(key, n, e);
255
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
256
#endif
257
}
258

259
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) {
1✔
260
   return botan_privkey_get_field(p, key, "p");
1✔
261
}
262

263
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) {
1✔
264
   return botan_privkey_get_field(q, key, "q");
1✔
265
}
266

267
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) {
1✔
268
   return botan_privkey_get_field(n, key, "n");
1✔
269
}
270

271
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
272
   return botan_privkey_get_field(e, key, "e");
1✔
273
}
274

275
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
1✔
276
   return botan_privkey_get_field(d, key, "d");
1✔
277
}
278

279
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
280
   return botan_pubkey_get_field(e, key, "e");
1✔
281
}
282

283
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
284
   return botan_pubkey_get_field(n, key, "n");
1✔
285
}
286

287
int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
4✔
288
#if defined(BOTAN_HAS_RSA)
289
   return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
14✔
290
      if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
291
         if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
292
            return write_vec_output(out, out_len, rsa->private_key_bits());
293
         else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
294
            return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
295
         else
296
            return BOTAN_FFI_ERROR_BAD_FLAG;
297
      } else {
298
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
299
      }
300
   });
301
#else
302
   BOTAN_UNUSED(rsa_key, out, out_len, flags);
303
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
304
#endif
305
}
306

307
/* DSA specific operations */
308
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
309
#if defined(BOTAN_HAS_DSA)
310

311
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
312
      return BOTAN_FFI_ERROR_NULL_POINTER;
313
   }
314

315
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
316
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
317
   }
318

319
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
320
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
321
      Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
1✔
322
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
1✔
323
      *key = new botan_privkey_struct(std::move(dsa));
2✔
324
      return BOTAN_FFI_SUCCESS;
2✔
325
   });
2✔
326
#else
327
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
328
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
329
#endif
330
}
331

332
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) {
2✔
333
#if defined(BOTAN_HAS_DSA)
334
   *key = nullptr;
2✔
335

336
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
337
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
338
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
2✔
339
      *key = new botan_privkey_struct(std::move(dsa));
4✔
340
      return BOTAN_FFI_SUCCESS;
4✔
341
   });
6✔
342
#else
343
   BOTAN_UNUSED(key, p, q, g, x);
344
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
345
#endif
346
}
347

348
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) {
2✔
349
#if defined(BOTAN_HAS_DSA)
350
   *key = nullptr;
2✔
351

352
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
353
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
354
      auto dsa = std::make_unique<Botan::DSA_PublicKey>(group, safe_get(y));
2✔
355
      *key = new botan_pubkey_struct(std::move(dsa));
4✔
356
      return BOTAN_FFI_SUCCESS;
2✔
357
   });
6✔
358
#else
359
   BOTAN_UNUSED(key, p, q, g, y);
360
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
361
#endif
362
}
363

364
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
365
   return botan_privkey_get_field(x, key, "x");
2✔
366
}
367

368
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
2✔
369
   return botan_pubkey_get_field(p, key, "p");
2✔
370
}
371

372
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) {
2✔
373
   return botan_pubkey_get_field(q, key, "q");
2✔
374
}
375

376
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
377
   return botan_pubkey_get_field(g, key, "g");
2✔
378
}
379

380
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
381
   return botan_pubkey_get_field(y, key, "y");
2✔
382
}
383

384
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
385
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
386
}
387

388
/* ECDSA specific operations */
389

390
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key) {
1✔
391
#if defined(BOTAN_HAS_ECC_KEY)
392
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
393
      const Botan::Public_Key& pub_key = safe_get(key);
1✔
394
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
1✔
395

396
      if(ec_key == nullptr) {
1✔
397
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
398
      }
399

400
      return ec_key->domain().used_explicit_encoding() ? 1 : 0;
1✔
401
   });
1✔
402
#else
403
   BOTAN_UNUSED(key);
404
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
405
#endif
406
}
407

408
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
409
                            const botan_mp_t public_x,
410
                            const botan_mp_t public_y,
411
                            const char* curve_name) {
412
#if defined(BOTAN_HAS_ECDSA)
413
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
414
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
415

416
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
417
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
418
         *key = new botan_pubkey_struct(std::move(p_key));
4✔
419
      }
420

421
      return rc;
2✔
422
   });
4✔
423
#else
424
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
425
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
426
#endif
427
}
428

429
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
430
#if defined(BOTAN_HAS_ECDSA)
431
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
432
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
2✔
433
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
2✔
434
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
435
         *key = new botan_privkey_struct(std::move(p_key));
4✔
436
      }
437
      return rc;
2✔
438
   });
4✔
439
#else
440
   BOTAN_UNUSED(key, scalar, curve_name);
441
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
442
#endif
443
}
444

445
/* ElGamal specific operations */
446
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
447
#if defined(BOTAN_HAS_ELGAMAL)
448

449
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
450
      return BOTAN_FFI_ERROR_NULL_POINTER;
451
   }
452

453
   if((pbits < 1024) || (qbits < 160)) {
1✔
454
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
455
   }
456

457
   Botan::DL_Group::PrimeType prime_type =
1✔
458
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
459

460
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
461
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
462
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
463
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
464
      *key = new botan_privkey_struct(std::move(elg));
2✔
465
      return BOTAN_FFI_SUCCESS;
2✔
466
   });
2✔
467
#else
468
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
469
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
470
#endif
471
}
472

473
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
2✔
474
#if defined(BOTAN_HAS_ELGAMAL)
475
   *key = nullptr;
2✔
476
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
477
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
478
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
2✔
479
      *key = new botan_pubkey_struct(std::move(elg));
4✔
480
      return BOTAN_FFI_SUCCESS;
2✔
481
   });
6✔
482
#else
483
   BOTAN_UNUSED(key, p, g, y);
484
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
485
#endif
486
}
487

488
int botan_privkey_load_elgamal(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
2✔
489
#if defined(BOTAN_HAS_ELGAMAL)
490
   *key = nullptr;
2✔
491
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
492
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
493
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(group, safe_get(x));
2✔
494
      *key = new botan_privkey_struct(std::move(elg));
4✔
495
      return BOTAN_FFI_SUCCESS;
4✔
496
   });
6✔
497
#else
498
   BOTAN_UNUSED(key, p, g, x);
499
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
500
#endif
501
}
502

503
/* Diffie Hellman specific operations */
504

505
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
506
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
507
}
508

509
int botan_privkey_load_dh(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
1✔
510
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
511
   *key = nullptr;
1✔
512
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
513
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
514
      auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
1✔
515
      *key = new botan_privkey_struct(std::move(dh));
2✔
516
      return BOTAN_FFI_SUCCESS;
2✔
517
   });
3✔
518
#else
519
   BOTAN_UNUSED(key, p, g, x);
520
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
521
#endif
522
}
523

524
int botan_pubkey_load_dh(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
1✔
525
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
526
   *key = nullptr;
1✔
527
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
528
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
529
      auto dh = std::make_unique<Botan::DH_PublicKey>(group, safe_get(y));
1✔
530
      *key = new botan_pubkey_struct(std::move(dh));
2✔
531
      return BOTAN_FFI_SUCCESS;
1✔
532
   });
3✔
533
#else
534
   BOTAN_UNUSED(key, p, g, y);
535
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
536
#endif
537
}
538

539
/* ECDH + x25519/x448 specific operations */
540

541
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
542
   if(param_str == nullptr) {
2✔
543
      return BOTAN_FFI_ERROR_NULL_POINTER;
544
   }
545

546
   const std::string params(param_str);
2✔
547

548
   if(params == "x25519" || params == "curve25519") {
2✔
549
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
550
   }
551

552
   if(params == "x448") {
2✔
553
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
554
   }
555

556
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
557
}
2✔
558

559
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
560
                           const botan_mp_t public_x,
561
                           const botan_mp_t public_y,
562
                           const char* curve_name) {
563
#if defined(BOTAN_HAS_ECDH)
564
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
565
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
566
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
567

568
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
569
         *key = new botan_pubkey_struct(std::move(p_key));
2✔
570
      }
571
      return rc;
1✔
572
   });
2✔
573
#else
574
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
575
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
576
#endif
577
}
578

579
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
4✔
580
#if defined(BOTAN_HAS_ECDH)
581
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
582
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
4✔
583
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
4✔
584
      if(rc == BOTAN_FFI_SUCCESS) {
4✔
585
         *key = new botan_privkey_struct(std::move(p_key));
8✔
586
      }
587
      return rc;
4✔
588
   });
8✔
589
#else
590
   BOTAN_UNUSED(key, scalar, curve_name);
591
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
592
#endif
593
}
594

595
/* SM2 specific operations */
596

597
int botan_pubkey_sm2_compute_za(
2✔
598
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
599
   if(out == nullptr || out_len == nullptr) {
2✔
600
      return BOTAN_FFI_ERROR_NULL_POINTER;
601
   }
602
   if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
603
      return BOTAN_FFI_ERROR_NULL_POINTER;
604
   }
605

606
#if defined(BOTAN_HAS_SM2)
607
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
608
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
609
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
610

611
      if(ec_key == nullptr) {
2✔
612
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
613
      }
614

615
      if(ec_key->algo_name() != "SM2") {
2✔
616
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
617
      }
618

619
      const std::string ident_str(ident);
2✔
620
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
621

622
      const std::vector<uint8_t> za = Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), ec_key->public_point());
2✔
623

624
      return write_vec_output(out, out_len, za);
2✔
625
   });
4✔
626
#else
627
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
628
#endif
629
}
630

631
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
632
                          const botan_mp_t public_x,
633
                          const botan_mp_t public_y,
634
                          const char* curve_name) {
635
#if defined(BOTAN_HAS_SM2)
636
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
637
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
3✔
638
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
3✔
639
         *key = new botan_pubkey_struct(std::move(p_key));
6✔
640
         return BOTAN_FFI_SUCCESS;
3✔
641
      }
642
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
643
   });
6✔
644
#else
645
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
646
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
647
#endif
648
}
649

650
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
651
#if defined(BOTAN_HAS_SM2)
652
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
653
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
654
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
655

656
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
657
         *key = new botan_privkey_struct(std::move(p_key));
6✔
658
      }
659
      return rc;
3✔
660
   });
6✔
661
#else
662
   BOTAN_UNUSED(key, scalar, curve_name);
663
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
664
#endif
665
}
666

667
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
668
                              const botan_mp_t public_x,
669
                              const botan_mp_t public_y,
670
                              const char* curve_name) {
671
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
672
}
673

674
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
675
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
676
}
677

678
/* Ed25519 specific operations */
679

680
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
681
#if defined(BOTAN_HAS_ED25519)
682
   *key = nullptr;
1✔
683
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
684
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
685
      auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
1✔
686
      *key = new botan_privkey_struct(std::move(ed25519));
2✔
687
      return BOTAN_FFI_SUCCESS;
2✔
688
   });
3✔
689
#else
690
   BOTAN_UNUSED(key, privkey);
691
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
692
#endif
693
}
694

695
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
696
#if defined(BOTAN_HAS_ED25519)
697
   *key = nullptr;
1✔
698
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
699
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
700
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
701
      *key = new botan_pubkey_struct(std::move(ed25519));
2✔
702
      return BOTAN_FFI_SUCCESS;
1✔
703
   });
3✔
704
#else
705
   BOTAN_UNUSED(key, pubkey);
706
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
707
#endif
708
}
709

710
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
711
#if defined(BOTAN_HAS_ED25519)
712
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
713
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
714
         const auto ed_key = ed->raw_private_key_bits();
715
         if(ed_key.size() != 64)
716
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
717
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
718
         return BOTAN_FFI_SUCCESS;
719
      } else {
720
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
721
      }
722
   });
723
#else
724
   BOTAN_UNUSED(key, output);
725
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
726
#endif
727
}
728

729
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
730
#if defined(BOTAN_HAS_ED25519)
731
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
732
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
733
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
734
         if(ed_key.size() != 32)
735
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
736
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
737
         return BOTAN_FFI_SUCCESS;
738
      } else {
739
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
740
      }
741
   });
742
#else
743
   BOTAN_UNUSED(key, output);
744
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
745
#endif
746
}
747

748
/* Ed448 specific operations */
749

750
int botan_privkey_load_ed448(botan_privkey_t* key, const uint8_t privkey[57]) {
1✔
751
#if defined(BOTAN_HAS_ED448)
752
   *key = nullptr;
1✔
753
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
754
      auto ed448 = std::make_unique<Botan::Ed448_PrivateKey>(std::span(privkey, 57));
1✔
755
      *key = new botan_privkey_struct(std::move(ed448));
2✔
756
      return BOTAN_FFI_SUCCESS;
1✔
757
   });
2✔
758
#else
759
   BOTAN_UNUSED(key, privkey);
760
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
761
#endif
762
}
763

764
int botan_pubkey_load_ed448(botan_pubkey_t* key, const uint8_t pubkey[57]) {
1✔
765
#if defined(BOTAN_HAS_ED448)
766
   *key = nullptr;
1✔
767
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
768
      auto ed448 = std::make_unique<Botan::Ed448_PublicKey>(std::span(pubkey, 57));
1✔
769
      *key = new botan_pubkey_struct(std::move(ed448));
2✔
770
      return BOTAN_FFI_SUCCESS;
1✔
771
   });
2✔
772
#else
773
   BOTAN_UNUSED(key, pubkey);
774
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
775
#endif
776
}
777

778
int botan_privkey_ed448_get_privkey(botan_privkey_t key, uint8_t output[57]) {
1✔
779
#if defined(BOTAN_HAS_ED448)
780
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
781
      if(auto ed = dynamic_cast<const Botan::Ed448_PrivateKey*>(&k)) {
782
         const auto ed_key = ed->raw_private_key_bits();
783
         Botan::copy_mem(std::span(output, 57), ed_key);
784
         return BOTAN_FFI_SUCCESS;
785
      } else {
786
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
787
      }
788
   });
789
#else
790
   BOTAN_UNUSED(key, output);
791
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
792
#endif
793
}
794

795
int botan_pubkey_ed448_get_pubkey(botan_pubkey_t key, uint8_t output[57]) {
1✔
796
#if defined(BOTAN_HAS_ED448)
797
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
3✔
798
      if(auto ed = dynamic_cast<const Botan::Ed448_PublicKey*>(&k)) {
799
         const auto ed_key = ed->public_key_bits();
800
         Botan::copy_mem(std::span(output, 57), ed_key);
801
         return BOTAN_FFI_SUCCESS;
802
      } else {
803
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
804
      }
805
   });
806
#else
807
   BOTAN_UNUSED(key, output);
808
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
809
#endif
810
}
811

812
/* X25519 specific operations */
813

814
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
815
#if defined(BOTAN_HAS_X25519)
816
   *key = nullptr;
1✔
817
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
818
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
819
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
1✔
820
      *key = new botan_privkey_struct(std::move(x25519));
2✔
821
      return BOTAN_FFI_SUCCESS;
2✔
822
   });
3✔
823
#else
824
   BOTAN_UNUSED(key, privkey);
825
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
826
#endif
827
}
828

829
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
830
#if defined(BOTAN_HAS_X25519)
831
   *key = nullptr;
1✔
832
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
833
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
834
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(pubkey_vec);
1✔
835
      *key = new botan_pubkey_struct(std::move(x25519));
2✔
836
      return BOTAN_FFI_SUCCESS;
1✔
837
   });
3✔
838
#else
839
   BOTAN_UNUSED(key, pubkey);
840
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
841
#endif
842
}
843

844
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
845
#if defined(BOTAN_HAS_X25519)
846
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
847
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
848
         const auto x25519_key = x25519->raw_private_key_bits();
849
         if(x25519_key.size() != 32)
850
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
851
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
852
         return BOTAN_FFI_SUCCESS;
853
      } else {
854
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
855
      }
856
   });
857
#else
858
   BOTAN_UNUSED(key, output);
859
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
860
#endif
861
}
862

863
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
864
#if defined(BOTAN_HAS_X25519)
865
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
866
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
867
         const std::vector<uint8_t>& x25519_key = x25519->public_value();
868
         if(x25519_key.size() != 32)
869
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
870
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
871
         return BOTAN_FFI_SUCCESS;
872
      } else {
873
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
874
      }
875
   });
876
#else
877
   BOTAN_UNUSED(key, output);
878
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
879
#endif
880
}
881

882
/* X448 specific operations */
883

884
int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
1✔
885
#if defined(BOTAN_HAS_X448)
886
   *key = nullptr;
1✔
887
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
888
      auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span(privkey, 56));
1✔
889
      *key = new botan_privkey_struct(std::move(x448));
2✔
890
      return BOTAN_FFI_SUCCESS;
1✔
891
   });
2✔
892
#else
893
   BOTAN_UNUSED(key, privkey);
894
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
895
#endif
896
}
897

898
int botan_pubkey_load_x448(botan_pubkey_t* key, const uint8_t pubkey[56]) {
1✔
899
#if defined(BOTAN_HAS_X448)
900
   *key = nullptr;
1✔
901
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
902
      auto x448 = std::make_unique<Botan::X448_PublicKey>(std::span(pubkey, 56));
1✔
903
      *key = new botan_pubkey_struct(std::move(x448));
2✔
904
      return BOTAN_FFI_SUCCESS;
1✔
905
   });
2✔
906
#else
907
   BOTAN_UNUSED(key, pubkey);
908
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
909
#endif
910
}
911

912
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56]) {
1✔
913
#if defined(BOTAN_HAS_X448)
914
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
915
      if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
916
         const auto x448_key = x448->raw_private_key_bits();
917
         Botan::copy_mem(std::span(output, 56), x448_key);
918
         return BOTAN_FFI_SUCCESS;
919
      } else {
920
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
921
      }
922
   });
923
#else
924
   BOTAN_UNUSED(key, output);
925
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
926
#endif
927
}
928

929
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
2✔
930
#if defined(BOTAN_HAS_X448)
931
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
932
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
933
         const std::vector<uint8_t>& x448_key = x448->public_value();
934
         Botan::copy_mem(std::span(output, 56), x448_key);
935
         return BOTAN_FFI_SUCCESS;
936
      } else {
937
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
938
      }
939
   });
940
#else
941
   BOTAN_UNUSED(key, output);
942
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
943
#endif
944
}
945

946
/*
947
* Algorithm specific key operations: Kyber
948
*/
949

950
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
951
#if defined(BOTAN_HAS_KYBER)
952
   *key = nullptr;
4✔
953
   switch(key_len) {
4✔
954
      case 1632:
1✔
955
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
956
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 1632);
1✔
957
            auto kyber512 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber512_R3);
1✔
958
            *key = new botan_privkey_struct(std::move(kyber512));
1✔
959
            return BOTAN_FFI_SUCCESS;
2✔
960
         });
2✔
961
      case 2400:
2✔
962
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
963
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
2✔
964
            auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768_R3);
2✔
965
            *key = new botan_privkey_struct(std::move(kyber768));
2✔
966
            return BOTAN_FFI_SUCCESS;
4✔
967
         });
4✔
968
      case 3168:
1✔
969
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
970
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 3168);
1✔
971
            auto kyber1024 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber1024_R3);
1✔
972
            *key = new botan_privkey_struct(std::move(kyber1024));
1✔
973
            return BOTAN_FFI_SUCCESS;
2✔
974
         });
2✔
975
      default:
976
         BOTAN_UNUSED(key, privkey, key_len);
977
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
978
   }
979
#else
980
   BOTAN_UNUSED(key, key_len, privkey);
981
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
982
#endif
983
}
984

985
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
986
#if defined(BOTAN_HAS_KYBER)
987
   *key = nullptr;
4✔
988
   switch(key_len) {
4✔
989
      case 800:
1✔
990
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
991
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 800);
1✔
992
            auto kyber512 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber512_R3);
1✔
993
            *key = new botan_pubkey_struct(std::move(kyber512));
2✔
994
            return BOTAN_FFI_SUCCESS;
1✔
995
         });
2✔
996
      case 1184:
2✔
997
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
998
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
2✔
999
            auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768_R3);
2✔
1000
            *key = new botan_pubkey_struct(std::move(kyber768));
4✔
1001
            return BOTAN_FFI_SUCCESS;
2✔
1002
         });
4✔
1003
      case 1568:
1✔
1004
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
1005
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1568);
1✔
1006
            auto kyber1024 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber1024_R3);
1✔
1007
            *key = new botan_pubkey_struct(std::move(kyber1024));
2✔
1008
            return BOTAN_FFI_SUCCESS;
1✔
1009
         });
2✔
1010
      default:
1011
         BOTAN_UNUSED(key, pubkey, key_len);
1012
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1013
   }
1014
#else
1015
   BOTAN_UNUSED(key, pubkey, key_len);
1016
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1017
#endif
1018
}
1019

1020
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1021
#if defined(BOTAN_HAS_KYBER)
1022
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
12✔
1023
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1024
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1025
      } else {
1026
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1027
      }
1028
   });
1029
#else
1030
   BOTAN_UNUSED(key, ctx, view);
1031
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1032
#endif
1033
}
1034

1035
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1036
#if defined(BOTAN_HAS_KYBER)
1037
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1038
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1039
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1040
      } else {
1041
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1042
      }
1043
   });
1044
#else
1045
   BOTAN_UNUSED(key, ctx, view);
1046
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1047
#endif
1048
}
1049

1050
/*
1051
* Algorithm specific key operations: ML-KEM
1052
*/
1053

1054
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1055
#if defined(BOTAN_HAS_ML_KEM)
1056
   if(key == nullptr || privkey == nullptr || mlkem_mode == nullptr) {
4✔
1057
      return BOTAN_FFI_ERROR_NULL_POINTER;
1058
   }
1059

1060
   *key = nullptr;
4✔
1061

1062
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1063
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1064
      if(!mode.is_ml_kem()) {
4✔
1065
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1066
      }
1067

1068
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1069
      *key = new botan_privkey_struct(std::move(mlkem_key));
4✔
1070
      return BOTAN_FFI_SUCCESS;
4✔
1071
   });
4✔
1072
#else
1073
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1074
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1075
#endif
1076
}
1077

1078
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
4✔
1079
#if defined(BOTAN_HAS_ML_KEM)
1080
   if(key == nullptr || pubkey == nullptr || mlkem_mode == nullptr) {
4✔
1081
      return BOTAN_FFI_ERROR_NULL_POINTER;
1082
   }
1083

1084
   *key = nullptr;
4✔
1085

1086
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1087
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1088
      if(!mode.is_ml_kem()) {
4✔
1089
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1090
      }
1091

1092
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PublicKey>(std::span{pubkey, key_len}, mode.mode());
4✔
1093
      *key = new botan_pubkey_struct(std::move(mlkem_key));
8✔
1094
      return BOTAN_FFI_SUCCESS;
4✔
1095
   });
4✔
1096
#else
1097
   BOTAN_UNUSED(key, key_len, pubkey, mlkem_mode);
1098
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1099
#endif
1100
}
1101

1102
/*
1103
* Algorithm specific key operations: ML-DSA
1104
*/
1105

1106
int botan_privkey_load_ml_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mldsa_mode) {
4✔
1107
#if defined(BOTAN_HAS_ML_DSA)
1108
   if(key == nullptr || privkey == nullptr || mldsa_mode == nullptr) {
4✔
1109
      return BOTAN_FFI_ERROR_NULL_POINTER;
1110
   }
1111

1112
   *key = nullptr;
4✔
1113

1114
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1115
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1116
      if(!mode.is_ml_dsa()) {
4✔
1117
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1118
      }
1119

1120
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1121
      *key = new botan_privkey_struct(std::move(mldsa_key));
4✔
1122
      return BOTAN_FFI_SUCCESS;
4✔
1123
   });
4✔
1124
#else
1125
   BOTAN_UNUSED(key, key_len, privkey, mldsa_mode);
1126
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1127
#endif
1128
}
1129

1130
int botan_pubkey_load_ml_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mldsa_mode) {
4✔
1131
#if defined(BOTAN_HAS_ML_DSA)
1132
   if(key == nullptr || pubkey == nullptr || mldsa_mode == nullptr) {
4✔
1133
      return BOTAN_FFI_ERROR_NULL_POINTER;
1134
   }
1135

1136
   *key = nullptr;
4✔
1137

1138
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1139
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1140
      if(!mode.is_ml_dsa()) {
4✔
1141
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1142
      }
1143

1144
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
4✔
1145
      *key = new botan_pubkey_struct(std::move(mldsa_key));
8✔
1146
      return BOTAN_FFI_SUCCESS;
4✔
1147
   });
4✔
1148
#else
1149
   BOTAN_UNUSED(key, key_len, pubkey, mldsa_mode);
1150
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1151
#endif
1152
}
1153

1154
/*
1155
* Algorithm specific key operations: SLH-DSA
1156
*/
1157

1158
int botan_privkey_load_slh_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1159
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1160
   if(key == nullptr || privkey == nullptr || slhdsa_mode == nullptr) {
13✔
1161
      return BOTAN_FFI_ERROR_NULL_POINTER;
1162
   }
1163

1164
   *key = nullptr;
13✔
1165

1166
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1167
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1168
      if(!mode.is_slh_dsa()) {
13✔
1169
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1170
      }
1171

1172
      auto slhdsa_key = std::make_unique<Botan::SLH_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1173
      *key = new botan_privkey_struct(std::move(slhdsa_key));
13✔
1174
      return BOTAN_FFI_SUCCESS;
13✔
1175
   });
13✔
1176
#else
1177
   BOTAN_UNUSED(key, key_len, privkey, slhdsa_mode);
1178
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1179
#endif
1180
}
1181

1182
int botan_pubkey_load_slh_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1183
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1184
   if(key == nullptr || pubkey == nullptr || slhdsa_mode == nullptr) {
13✔
1185
      return BOTAN_FFI_ERROR_NULL_POINTER;
1186
   }
1187

1188
   *key = nullptr;
13✔
1189

1190
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1191
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1192
      if(!mode.is_slh_dsa()) {
13✔
1193
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1194
      }
1195

1196
      auto mldsa_key = std::make_unique<Botan::SLH_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1197
      *key = new botan_pubkey_struct(std::move(mldsa_key));
26✔
1198
      return BOTAN_FFI_SUCCESS;
13✔
1199
   });
13✔
1200
#else
1201
   BOTAN_UNUSED(key, key_len, pubkey, slhdsa_mode);
1202
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1203
#endif
1204
}
1205

1206
/*
1207
* Algorithm specific key operations: FrodoKEM
1208
*/
1209

1210
int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* frodo_mode) {
13✔
1211
#if defined(BOTAN_HAS_FRODOKEM)
1212
   if(key == nullptr || privkey == nullptr || frodo_mode == nullptr) {
13✔
1213
      return BOTAN_FFI_ERROR_NULL_POINTER;
1214
   }
1215

1216
   *key = nullptr;
13✔
1217

1218
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1219
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1220
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1221
      *key = new botan_privkey_struct(std::move(frodo_key));
13✔
1222
      return BOTAN_FFI_SUCCESS;
13✔
1223
   });
13✔
1224
#else
1225
   BOTAN_UNUSED(key, privkey, key_len, frodo_mode);
1226
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1227
#endif
1228
}
1229

1230
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode) {
13✔
1231
#if defined(BOTAN_HAS_FRODOKEM)
1232
   if(key == nullptr || pubkey == nullptr || frodo_mode == nullptr) {
13✔
1233
      return BOTAN_FFI_ERROR_NULL_POINTER;
1234
   }
1235

1236
   *key = nullptr;
13✔
1237

1238
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1239
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1240
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1241
      *key = new botan_pubkey_struct(std::move(frodo_key));
26✔
1242
      return BOTAN_FFI_SUCCESS;
13✔
1243
   });
13✔
1244
#else
1245
   BOTAN_UNUSED(key, pubkey, key_len, frodo_mode);
1246
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1247
#endif
1248
}
1249

1250
/*
1251
* Algorithm specific key operations : Classic McEliece
1252
*/
1253

1254
int botan_privkey_load_classic_mceliece(botan_privkey_t* key,
17✔
1255
                                        const uint8_t privkey[],
1256
                                        size_t key_len,
1257
                                        const char* cmce_mode) {
1258
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1259
   if(key == nullptr || privkey == nullptr || cmce_mode == nullptr) {
17✔
1260
      return BOTAN_FFI_ERROR_NULL_POINTER;
1261
   }
1262

1263
   *key = nullptr;
17✔
1264

1265
   return ffi_guard_thunk(__func__, [=]() -> int {
34✔
1266
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1267
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PrivateKey>(std::span{privkey, key_len}, mode);
17✔
1268
      *key = new botan_privkey_struct(std::move(cmce_key));
17✔
1269
      return BOTAN_FFI_SUCCESS;
17✔
1270
   });
17✔
1271
#else
1272
   BOTAN_UNUSED(key, privkey, key_len, cmce_mode);
1273
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1274
#endif
1275
}
1276

1277
int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
17✔
1278
                                       const uint8_t pubkey[],
1279
                                       size_t key_len,
1280
                                       const char* cmce_mode) {
1281
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1282
   if(key == nullptr || pubkey == nullptr || cmce_mode == nullptr) {
17✔
1283
      return BOTAN_FFI_ERROR_NULL_POINTER;
1284
   }
1285

1286
   *key = nullptr;
17✔
1287

1288
   return ffi_guard_thunk(__func__, [=]() -> int {
34✔
1289
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1290
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PublicKey>(std::span{pubkey, key_len}, mode);
17✔
1291
      *key = new botan_pubkey_struct(std::move(cmce_key));
34✔
1292
      return BOTAN_FFI_SUCCESS;
17✔
1293
   });
17✔
1294
#else
1295
   BOTAN_UNUSED(key, pubkey, key_len, cmce_mode);
1296
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1297
#endif
1298
}
1299

1300
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1301
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1302
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
1303
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1304
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
1305
         return invoke_view_callback(view, ctx, pt);
1306
      } else {
1307
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1308
      }
1309
   });
1310
#else
1311
   BOTAN_UNUSED(key, view, ctx);
1312
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1313
#endif
1314
}
1315

1316
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1317
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1318
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1319
}
1✔
1320

1321
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1322
                         const char* aead,
1323
                         const uint8_t ct[],
1324
                         size_t ct_len,
1325
                         const uint8_t ad[],
1326
                         size_t ad_len,
1327
                         uint8_t out[],
1328
                         size_t* out_len) {
1329
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1330
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1331
}
1332

1333
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1334
                         botan_rng_t rng_obj,
1335
                         const char* aead,
1336
                         const uint8_t pt[],
1337
                         size_t pt_len,
1338
                         const uint8_t ad[],
1339
                         size_t ad_len,
1340
                         uint8_t out[],
1341
                         size_t* out_len) {
1342
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1343
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1344
}
1345
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc