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

randombit / botan / 11331948318

14 Oct 2024 05:01PM UTC coverage: 91.128% (+0.008%) from 91.12%
11331948318

Pull #3893

github

web-flow
Merge 22a97fa1d into ed74c9542
Pull Request #3893: PQC: ML-KEM

90438 of 99243 relevant lines covered (91.13%)

8992513.48 hits per line

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

98.15
/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_ML_KEM)
75
   #include <botan/kyber.h>
76
   #include <botan/internal/kyber_constants.h>
77
#endif
78

79
#if defined(BOTAN_HAS_FRODOKEM)
80
   #include <botan/frodokem.h>
81
#endif
82

83
namespace {
84

85
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
86

87
// These are always called within an existing try/catch block
88

89
template <class ECPrivateKey_t>
90
int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& scalar, const char* curve_name) {
9✔
91
   if(curve_name == nullptr) {
9✔
92
      return BOTAN_FFI_ERROR_NULL_POINTER;
93
   }
94

95
   Botan::Null_RNG null_rng;
9✔
96
   const auto grp = Botan::EC_Group::from_name(curve_name);
9✔
97
   key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
9✔
98
   return BOTAN_FFI_SUCCESS;
99
}
9✔
100

101
template <class ECPublicKey_t>
102
int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
6✔
103
                   const Botan::BigInt& public_x,
104
                   const Botan::BigInt& public_y,
105
                   const char* curve_name) {
106
   if(curve_name == nullptr) {
6✔
107
      return BOTAN_FFI_ERROR_NULL_POINTER;
108
   }
109

110
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
111

112
   if(auto pt = Botan::EC_AffinePoint::from_bigint_xy(group, public_x, public_y)) {
6✔
113
      key.reset(new ECPublicKey_t(group, pt->to_legacy_point()));
6✔
114
      return BOTAN_FFI_SUCCESS;
6✔
115
   } else {
116
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
117
   }
118
}
6✔
119

120
#endif
121

122
Botan::BigInt pubkey_get_field(const Botan::Public_Key& key, std::string_view field) {
40✔
123
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
124
   // Not currently handled by get_int_field
125
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
40✔
126
      if(field == "public_x") {
15✔
127
         return ecc->public_point().get_affine_x();
8✔
128
      } else if(field == "public_y") {
7✔
129
         return ecc->public_point().get_affine_y();
6✔
130
      }
131
   }
132
#endif
133

134
   try {
26✔
135
      return key.get_int_field(field);
26✔
136
   } catch(Botan::Unknown_PK_Field_Name&) {
2✔
137
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
2✔
138
   }
2✔
139
}
140

141
Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
35✔
142
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
143
   // Not currently handled by get_int_field
144
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
35✔
145
      if(field == "public_x") {
16✔
146
         return ecc->public_point().get_affine_x();
2✔
147
      } else if(field == "public_y") {
14✔
148
         return ecc->public_point().get_affine_y();
4✔
149
      }
150
   }
151
#endif
152

153
   try {
29✔
154
      return key.get_int_field(field);
29✔
155
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
156
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
157
   }
4✔
158
}
159

160
}  // namespace
161

162
extern "C" {
163

164
using namespace Botan_FFI;
165

166
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
167
   if(field_name_cstr == nullptr) {
40✔
168
      return BOTAN_FFI_ERROR_NULL_POINTER;
169
   }
170

171
   const std::string field_name(field_name_cstr);
40✔
172

173
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
174
}
40✔
175

176
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
177
   if(field_name_cstr == nullptr) {
35✔
178
      return BOTAN_FFI_ERROR_NULL_POINTER;
179
   }
180

181
   const std::string field_name(field_name_cstr);
35✔
182

183
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
140✔
184
}
185

186
/* RSA specific operations */
187

188
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
1✔
189
   if(n_bits < 1024 || n_bits > 16 * 1024) {
1✔
190
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
191
   }
192

193
   std::string n_str = std::to_string(n_bits);
1✔
194

195
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
196
}
1✔
197

198
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✔
199
#if defined(BOTAN_HAS_RSA)
200
   *key = nullptr;
2✔
201

202
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
203
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
2✔
204
      *key = new botan_privkey_struct(std::move(rsa));
2✔
205
      return BOTAN_FFI_SUCCESS;
2✔
206
   });
4✔
207
#else
208
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
209
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
210
#endif
211
}
212

213
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
214
#if defined(BOTAN_HAS_RSA)
215
   *key = nullptr;
1✔
216

217
   Botan::secure_vector<uint8_t> src(bits, bits + len);
1✔
218
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
219
      Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
1✔
220
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
1✔
221
      *key = new botan_privkey_struct(std::move(rsa));
1✔
222
      return BOTAN_FFI_SUCCESS;
1✔
223
   });
1✔
224
#else
225
   BOTAN_UNUSED(key, bits, len);
226
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
227
#endif
228
}
1✔
229

230
int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e) {
4✔
231
#if defined(BOTAN_HAS_RSA)
232
   *key = nullptr;
4✔
233
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
234
      auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
4✔
235
      *key = new botan_pubkey_struct(std::move(rsa));
6✔
236
      return BOTAN_FFI_SUCCESS;
3✔
237
   });
7✔
238
#else
239
   BOTAN_UNUSED(key, n, e);
240
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
241
#endif
242
}
243

244
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) {
1✔
245
   return botan_privkey_get_field(p, key, "p");
1✔
246
}
247

248
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) {
1✔
249
   return botan_privkey_get_field(q, key, "q");
1✔
250
}
251

252
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) {
1✔
253
   return botan_privkey_get_field(n, key, "n");
1✔
254
}
255

256
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
257
   return botan_privkey_get_field(e, key, "e");
1✔
258
}
259

260
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
1✔
261
   return botan_privkey_get_field(d, key, "d");
1✔
262
}
263

264
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
265
   return botan_pubkey_get_field(e, key, "e");
1✔
266
}
267

268
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
269
   return botan_pubkey_get_field(n, key, "n");
1✔
270
}
271

272
int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
4✔
273
#if defined(BOTAN_HAS_RSA)
274
   return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
14✔
275
      if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
276
         if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
277
            return write_vec_output(out, out_len, rsa->private_key_bits());
278
         else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
279
            return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
280
         else
281
            return BOTAN_FFI_ERROR_BAD_FLAG;
282
      } else {
283
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
284
      }
285
   });
286
#else
287
   BOTAN_UNUSED(rsa_key, out, out_len, flags);
288
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
289
#endif
290
}
291

292
/* DSA specific operations */
293
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
294
#if defined(BOTAN_HAS_DSA)
295

296
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
297
      return BOTAN_FFI_ERROR_NULL_POINTER;
298
   }
299

300
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
301
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
302
   }
303

304
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
305
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
306
      Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
1✔
307
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
1✔
308
      *key = new botan_privkey_struct(std::move(dsa));
2✔
309
      return BOTAN_FFI_SUCCESS;
2✔
310
   });
2✔
311
#else
312
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
313
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
314
#endif
315
}
316

317
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✔
318
#if defined(BOTAN_HAS_DSA)
319
   *key = nullptr;
2✔
320

321
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
322
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
323
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
2✔
324
      *key = new botan_privkey_struct(std::move(dsa));
4✔
325
      return BOTAN_FFI_SUCCESS;
4✔
326
   });
6✔
327
#else
328
   BOTAN_UNUSED(key, p, q, g, x);
329
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
330
#endif
331
}
332

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

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

349
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
350
   return botan_privkey_get_field(x, key, "x");
2✔
351
}
352

353
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
2✔
354
   return botan_pubkey_get_field(p, key, "p");
2✔
355
}
356

357
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) {
2✔
358
   return botan_pubkey_get_field(q, key, "q");
2✔
359
}
360

361
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
362
   return botan_pubkey_get_field(g, key, "g");
2✔
363
}
364

365
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
366
   return botan_pubkey_get_field(y, key, "y");
2✔
367
}
368

369
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
370
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
371
}
372

373
/* ECDSA specific operations */
374

375
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key) {
1✔
376
#if defined(BOTAN_HAS_ECC_KEY)
377
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
378
      const Botan::Public_Key& pub_key = safe_get(key);
1✔
379
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
1✔
380

381
      if(ec_key == nullptr) {
1✔
382
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
383
      }
384

385
      return ec_key->domain().used_explicit_encoding() ? 1 : 0;
1✔
386
   });
1✔
387
#else
388
   BOTAN_UNUSED(key);
389
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
390
#endif
391
}
392

393
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
394
                            const botan_mp_t public_x,
395
                            const botan_mp_t public_y,
396
                            const char* curve_name) {
397
#if defined(BOTAN_HAS_ECDSA)
398
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
399
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
400

401
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
402
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
403
         *key = new botan_pubkey_struct(std::move(p_key));
4✔
404
      }
405

406
      return rc;
2✔
407
   });
4✔
408
#else
409
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
410
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
411
#endif
412
}
413

414
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
415
#if defined(BOTAN_HAS_ECDSA)
416
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
417
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
2✔
418
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
2✔
419
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
420
         *key = new botan_privkey_struct(std::move(p_key));
4✔
421
      }
422
      return rc;
2✔
423
   });
4✔
424
#else
425
   BOTAN_UNUSED(key, scalar, curve_name);
426
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
427
#endif
428
}
429

430
/* ElGamal specific operations */
431
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
432
#if defined(BOTAN_HAS_ELGAMAL)
433

434
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
435
      return BOTAN_FFI_ERROR_NULL_POINTER;
436
   }
437

438
   if((pbits < 1024) || (qbits < 160)) {
1✔
439
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
440
   }
441

442
   Botan::DL_Group::PrimeType prime_type =
1✔
443
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
444

445
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
446
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
447
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
448
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
449
      *key = new botan_privkey_struct(std::move(elg));
2✔
450
      return BOTAN_FFI_SUCCESS;
2✔
451
   });
2✔
452
#else
453
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
454
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
455
#endif
456
}
457

458
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
2✔
459
#if defined(BOTAN_HAS_ELGAMAL)
460
   *key = nullptr;
2✔
461
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
462
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
463
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
2✔
464
      *key = new botan_pubkey_struct(std::move(elg));
4✔
465
      return BOTAN_FFI_SUCCESS;
2✔
466
   });
6✔
467
#else
468
   BOTAN_UNUSED(key, p, g, y);
469
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
470
#endif
471
}
472

473
int botan_privkey_load_elgamal(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
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_PrivateKey>(group, safe_get(x));
2✔
479
      *key = new botan_privkey_struct(std::move(elg));
4✔
480
      return BOTAN_FFI_SUCCESS;
4✔
481
   });
6✔
482
#else
483
   BOTAN_UNUSED(key, p, g, x);
484
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
485
#endif
486
}
487

488
/* Diffie Hellman specific operations */
489

490
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
491
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
492
}
493

494
int botan_privkey_load_dh(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
1✔
495
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
496
   *key = nullptr;
1✔
497
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
498
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
499
      auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
1✔
500
      *key = new botan_privkey_struct(std::move(dh));
2✔
501
      return BOTAN_FFI_SUCCESS;
2✔
502
   });
3✔
503
#else
504
   BOTAN_UNUSED(key, p, g, x);
505
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
506
#endif
507
}
508

509
int botan_pubkey_load_dh(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
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_PublicKey>(group, safe_get(y));
1✔
515
      *key = new botan_pubkey_struct(std::move(dh));
2✔
516
      return BOTAN_FFI_SUCCESS;
1✔
517
   });
3✔
518
#else
519
   BOTAN_UNUSED(key, p, g, y);
520
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
521
#endif
522
}
523

524
/* ECDH + x25519/x448 specific operations */
525

526
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
527
   if(param_str == nullptr) {
2✔
528
      return BOTAN_FFI_ERROR_NULL_POINTER;
529
   }
530

531
   const std::string params(param_str);
2✔
532

533
   if(params == "x25519" || params == "curve25519") {
2✔
534
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
535
   }
536

537
   if(params == "x448") {
2✔
538
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
539
   }
540

541
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
542
}
2✔
543

544
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
545
                           const botan_mp_t public_x,
546
                           const botan_mp_t public_y,
547
                           const char* curve_name) {
548
#if defined(BOTAN_HAS_ECDH)
549
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
550
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
551
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
552

553
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
554
         *key = new botan_pubkey_struct(std::move(p_key));
2✔
555
      }
556
      return rc;
1✔
557
   });
2✔
558
#else
559
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
560
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
561
#endif
562
}
563

564
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
4✔
565
#if defined(BOTAN_HAS_ECDH)
566
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
567
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
4✔
568
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
4✔
569
      if(rc == BOTAN_FFI_SUCCESS) {
4✔
570
         *key = new botan_privkey_struct(std::move(p_key));
8✔
571
      }
572
      return rc;
4✔
573
   });
8✔
574
#else
575
   BOTAN_UNUSED(key, scalar, curve_name);
576
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
577
#endif
578
}
579

580
/* SM2 specific operations */
581

582
int botan_pubkey_sm2_compute_za(
2✔
583
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
584
   if(out == nullptr || out_len == nullptr) {
2✔
585
      return BOTAN_FFI_ERROR_NULL_POINTER;
586
   }
587
   if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
588
      return BOTAN_FFI_ERROR_NULL_POINTER;
589
   }
590

591
#if defined(BOTAN_HAS_SM2)
592
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
593
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
594
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
595

596
      if(ec_key == nullptr) {
2✔
597
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
598
      }
599

600
      if(ec_key->algo_name() != "SM2") {
2✔
601
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
602
      }
603

604
      const std::string ident_str(ident);
2✔
605
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
606

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

609
      return write_vec_output(out, out_len, za);
2✔
610
   });
4✔
611
#else
612
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
613
#endif
614
}
615

616
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
617
                          const botan_mp_t public_x,
618
                          const botan_mp_t public_y,
619
                          const char* curve_name) {
620
#if defined(BOTAN_HAS_SM2)
621
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
622
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
3✔
623
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
3✔
624
         *key = new botan_pubkey_struct(std::move(p_key));
6✔
625
         return BOTAN_FFI_SUCCESS;
3✔
626
      }
627
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
628
   });
6✔
629
#else
630
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
631
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
632
#endif
633
}
634

635
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
636
#if defined(BOTAN_HAS_SM2)
637
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
638
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
639
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
640

641
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
642
         *key = new botan_privkey_struct(std::move(p_key));
6✔
643
      }
644
      return rc;
3✔
645
   });
6✔
646
#else
647
   BOTAN_UNUSED(key, scalar, curve_name);
648
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
649
#endif
650
}
651

652
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
653
                              const botan_mp_t public_x,
654
                              const botan_mp_t public_y,
655
                              const char* curve_name) {
656
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
657
}
658

659
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
660
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
661
}
662

663
/* Ed25519 specific operations */
664

665
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
666
#if defined(BOTAN_HAS_ED25519)
667
   *key = nullptr;
1✔
668
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
669
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
670
      auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
1✔
671
      *key = new botan_privkey_struct(std::move(ed25519));
2✔
672
      return BOTAN_FFI_SUCCESS;
2✔
673
   });
3✔
674
#else
675
   BOTAN_UNUSED(key, privkey);
676
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
677
#endif
678
}
679

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

695
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
696
#if defined(BOTAN_HAS_ED25519)
697
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
698
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
699
         const auto ed_key = ed->raw_private_key_bits();
700
         if(ed_key.size() != 64)
701
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
702
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
703
         return BOTAN_FFI_SUCCESS;
704
      } else {
705
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
706
      }
707
   });
708
#else
709
   BOTAN_UNUSED(key, output);
710
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
711
#endif
712
}
713

714
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
715
#if defined(BOTAN_HAS_ED25519)
716
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
717
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
718
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
719
         if(ed_key.size() != 32)
720
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
721
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
722
         return BOTAN_FFI_SUCCESS;
723
      } else {
724
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
725
      }
726
   });
727
#else
728
   BOTAN_UNUSED(key, output);
729
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
730
#endif
731
}
732

733
/* Ed448 specific operations */
734

735
int botan_privkey_load_ed448(botan_privkey_t* key, const uint8_t privkey[57]) {
1✔
736
#if defined(BOTAN_HAS_ED448)
737
   *key = nullptr;
1✔
738
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
739
      auto ed448 = std::make_unique<Botan::Ed448_PrivateKey>(std::span(privkey, 57));
1✔
740
      *key = new botan_privkey_struct(std::move(ed448));
2✔
741
      return BOTAN_FFI_SUCCESS;
1✔
742
   });
2✔
743
#else
744
   BOTAN_UNUSED(key, privkey);
745
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
746
#endif
747
}
748

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

763
int botan_privkey_ed448_get_privkey(botan_privkey_t key, uint8_t output[57]) {
1✔
764
#if defined(BOTAN_HAS_ED448)
765
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
766
      if(auto ed = dynamic_cast<const Botan::Ed448_PrivateKey*>(&k)) {
767
         const auto ed_key = ed->raw_private_key_bits();
768
         Botan::copy_mem(std::span(output, 57), ed_key);
769
         return BOTAN_FFI_SUCCESS;
770
      } else {
771
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
772
      }
773
   });
774
#else
775
   BOTAN_UNUSED(key, output);
776
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
777
#endif
778
}
779

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

797
/* X25519 specific operations */
798

799
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
800
#if defined(BOTAN_HAS_X25519)
801
   *key = nullptr;
1✔
802
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
803
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
804
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
1✔
805
      *key = new botan_privkey_struct(std::move(x25519));
2✔
806
      return BOTAN_FFI_SUCCESS;
2✔
807
   });
3✔
808
#else
809
   BOTAN_UNUSED(key, privkey);
810
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
811
#endif
812
}
813

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

829
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
830
#if defined(BOTAN_HAS_X25519)
831
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
832
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
833
         const auto x25519_key = x25519->raw_private_key_bits();
834
         if(x25519_key.size() != 32)
835
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
836
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
837
         return BOTAN_FFI_SUCCESS;
838
      } else {
839
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
840
      }
841
   });
842
#else
843
   BOTAN_UNUSED(key, output);
844
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
845
#endif
846
}
847

848
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
849
#if defined(BOTAN_HAS_X25519)
850
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
851
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
852
         const std::vector<uint8_t>& x25519_key = x25519->public_value();
853
         if(x25519_key.size() != 32)
854
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
855
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
856
         return BOTAN_FFI_SUCCESS;
857
      } else {
858
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
859
      }
860
   });
861
#else
862
   BOTAN_UNUSED(key, output);
863
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
864
#endif
865
}
866

867
/* X448 specific operations */
868

869
int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
1✔
870
#if defined(BOTAN_HAS_X448)
871
   *key = nullptr;
1✔
872
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
873
      auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span(privkey, 56));
1✔
874
      *key = new botan_privkey_struct(std::move(x448));
2✔
875
      return BOTAN_FFI_SUCCESS;
1✔
876
   });
2✔
877
#else
878
   BOTAN_UNUSED(key, privkey);
879
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
880
#endif
881
}
882

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

897
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56]) {
1✔
898
#if defined(BOTAN_HAS_X448)
899
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
900
      if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
901
         const auto x448_key = x448->raw_private_key_bits();
902
         Botan::copy_mem(std::span(output, 56), x448_key);
903
         return BOTAN_FFI_SUCCESS;
904
      } else {
905
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
906
      }
907
   });
908
#else
909
   BOTAN_UNUSED(key, output);
910
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
911
#endif
912
}
913

914
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
2✔
915
#if defined(BOTAN_HAS_X448)
916
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
917
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
918
         const std::vector<uint8_t>& x448_key = x448->public_value();
919
         Botan::copy_mem(std::span(output, 56), x448_key);
920
         return BOTAN_FFI_SUCCESS;
921
      } else {
922
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
923
      }
924
   });
925
#else
926
   BOTAN_UNUSED(key, output);
927
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
928
#endif
929
}
930

931
/*
932
* Algorithm specific key operations: Kyber
933
*/
934

935
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
936
#if defined(BOTAN_HAS_KYBER)
937
   *key = nullptr;
4✔
938
   switch(key_len) {
4✔
939
      case 1632:
1✔
940
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
941
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 1632);
1✔
942
            auto kyber512 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber512_R3);
1✔
943
            *key = new botan_privkey_struct(std::move(kyber512));
1✔
944
            return BOTAN_FFI_SUCCESS;
2✔
945
         });
2✔
946
      case 2400:
2✔
947
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
948
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
2✔
949
            auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768_R3);
2✔
950
            *key = new botan_privkey_struct(std::move(kyber768));
2✔
951
            return BOTAN_FFI_SUCCESS;
4✔
952
         });
4✔
953
      case 3168:
1✔
954
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
955
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 3168);
1✔
956
            auto kyber1024 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber1024_R3);
1✔
957
            *key = new botan_privkey_struct(std::move(kyber1024));
1✔
958
            return BOTAN_FFI_SUCCESS;
2✔
959
         });
2✔
960
      default:
961
         BOTAN_UNUSED(key, privkey, key_len);
962
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
963
   }
964
#else
965
   BOTAN_UNUSED(key, key_len, privkey);
966
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
967
#endif
968
}
969

970
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
971
#if defined(BOTAN_HAS_KYBER)
972
   *key = nullptr;
4✔
973
   switch(key_len) {
4✔
974
      case 800:
1✔
975
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
976
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 800);
1✔
977
            auto kyber512 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber512_R3);
1✔
978
            *key = new botan_pubkey_struct(std::move(kyber512));
2✔
979
            return BOTAN_FFI_SUCCESS;
1✔
980
         });
2✔
981
      case 1184:
2✔
982
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
983
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
2✔
984
            auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768_R3);
2✔
985
            *key = new botan_pubkey_struct(std::move(kyber768));
4✔
986
            return BOTAN_FFI_SUCCESS;
2✔
987
         });
4✔
988
      case 1568:
1✔
989
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
990
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1568);
1✔
991
            auto kyber1024 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber1024_R3);
1✔
992
            *key = new botan_pubkey_struct(std::move(kyber1024));
2✔
993
            return BOTAN_FFI_SUCCESS;
1✔
994
         });
2✔
995
      default:
996
         BOTAN_UNUSED(key, pubkey, key_len);
997
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
998
   }
999
#else
1000
   BOTAN_UNUSED(key, pubkey, key_len);
1001
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1002
#endif
1003
}
1004

1005
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1006
#if defined(BOTAN_HAS_KYBER)
1007
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
12✔
1008
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1009
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1010
      } else {
1011
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1012
      }
1013
   });
1014
#else
1015
   BOTAN_UNUSED(key, ctx, view);
1016
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1017
#endif
1018
}
1019

1020
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1021
#if defined(BOTAN_HAS_KYBER)
1022
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1023
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1024
         return invoke_view_callback(view, ctx, kyber->public_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
/*
1036
* Algorithm specific key operations: ML-KEM
1037
*/
1038

1039
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1040
#if defined(BOTAN_HAS_ML_KEM)
1041
   *key = nullptr;
4✔
1042

1043
   if(privkey == nullptr || mlkem_mode == nullptr) {
4✔
1044
      return BOTAN_FFI_ERROR_NULL_POINTER;
1045
   }
1046

1047
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1048
      auto mode = Botan::KyberConstants(Botan::KyberMode(mlkem_mode));
4✔
1049
      if(!mode.mode().is_ml_kem()) {
4✔
1050
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1051
      }
1052

1053
      if(key_len != mode.private_key_bytes()) {
4✔
1054
         return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
1055
      }
1056

1057
      auto mlkem_key = std::make_unique<Botan::Kyber_PrivateKey>(std::span{privkey, key_len}, mode.mode());
4✔
1058
      *key = new botan_privkey_struct(std::move(mlkem_key));
4✔
1059
      return BOTAN_FFI_SUCCESS;
4✔
1060
   });
4✔
1061
#else
1062
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1063
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1064
#endif
1065
}
1066

1067
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
4✔
1068
#if defined(BOTAN_HAS_ML_KEM)
1069
   *key = nullptr;
4✔
1070

1071
   if(pubkey == nullptr || mlkem_mode == nullptr) {
4✔
1072
      return BOTAN_FFI_ERROR_NULL_POINTER;
1073
   }
1074

1075
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1076
      auto mode = Botan::KyberConstants(Botan::KyberMode(mlkem_mode));
4✔
1077
      if(!mode.mode().is_ml_kem()) {
4✔
1078
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1079
      }
1080

1081
      if(key_len != mode.public_key_bytes()) {
4✔
1082
         return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
1083
      }
1084

1085
      auto mlkem_key = std::make_unique<Botan::Kyber_PublicKey>(std::span{pubkey, key_len}, mode.mode());
4✔
1086
      *key = new botan_pubkey_struct(std::move(mlkem_key));
8✔
1087
      return BOTAN_FFI_SUCCESS;
4✔
1088
   });
4✔
1089
#else
1090
   BOTAN_UNUSED(key, key_len, pubkey, mlkem_mode);
1091
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1092
#endif
1093
}
1094

1095
/*
1096
* Algorithm specific key operations: FrodoKEM
1097
*/
1098

1099
int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* frodo_mode) {
13✔
1100
#if defined(BOTAN_HAS_FRODOKEM)
1101
   if(key == nullptr || privkey == nullptr || frodo_mode == nullptr) {
13✔
1102
      return BOTAN_FFI_ERROR_NULL_POINTER;
1103
   }
1104

1105
   *key = nullptr;
13✔
1106

1107
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1108
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1109
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1110
      *key = new botan_privkey_struct(std::move(frodo_key));
13✔
1111
      return BOTAN_FFI_SUCCESS;
13✔
1112
   });
13✔
1113
#else
1114
   BOTAN_UNUSED(key, privkey, key_len, frodo_mode);
1115
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1116
#endif
1117
}
1118

1119
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode) {
13✔
1120
#if defined(BOTAN_HAS_FRODOKEM)
1121
   if(key == nullptr || pubkey == nullptr || frodo_mode == nullptr) {
13✔
1122
      return BOTAN_FFI_ERROR_NULL_POINTER;
1123
   }
1124

1125
   *key = nullptr;
13✔
1126

1127
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1128
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1129
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1130
      *key = new botan_pubkey_struct(std::move(frodo_key));
26✔
1131
      return BOTAN_FFI_SUCCESS;
13✔
1132
   });
13✔
1133
#else
1134
   BOTAN_UNUSED(key, privkey, key_len, frodo_mode);
1135
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1136
#endif
1137
}
1138

1139
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1140
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1141
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
1142
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1143
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
1144
         return invoke_view_callback(view, ctx, pt);
1145
      } else {
1146
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1147
      }
1148
   });
1149
#else
1150
   BOTAN_UNUSED(key, view, ctx);
1151
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1152
#endif
1153
}
1154

1155
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1156
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1157
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1158
}
1✔
1159

1160
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1161
                         const char* aead,
1162
                         const uint8_t ct[],
1163
                         size_t ct_len,
1164
                         const uint8_t ad[],
1165
                         size_t ad_len,
1166
                         uint8_t out[],
1167
                         size_t* out_len) {
1168
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1169
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1170
}
1171

1172
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1173
                         botan_rng_t rng_obj,
1174
                         const char* aead,
1175
                         const uint8_t pt[],
1176
                         size_t pt_len,
1177
                         const uint8_t ad[],
1178
                         size_t ad_len,
1179
                         uint8_t out[],
1180
                         size_t* out_len) {
1181
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1182
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1183
}
1184
}
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