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

randombit / botan / 16248620128

13 Jul 2025 11:27AM UTC coverage: 90.565% (-0.01%) from 90.575%
16248620128

push

github

web-flow
Merge pull request #4983 from randombit/jack/clang-tidy-cppcoreguidelines-owning-memory

Enable and fix clang-tidy warning cppcoreguidelines-owning-memory

99026 of 109342 relevant lines covered (90.57%)

12444574.04 hits per line

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

97.89
/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
   if(!Botan::EC_Group::supports_named_group(curve_name)) {
9✔
110
      return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
111
   }
112

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

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

128
   if(!Botan::EC_Group::supports_named_group(curve_name)) {
6✔
129
      return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
130
   }
131

132
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
133

134
   if(auto pt = Botan::EC_AffinePoint::from_bigint_xy(group, public_x, public_y)) {
6✔
135
      key.reset(new ECPublicKey_t(group, pt.value()));
6✔
136
      return BOTAN_FFI_SUCCESS;
6✔
137
   } else {
138
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
139
   }
140
}
6✔
141

142
#endif
143

144
Botan::BigInt pubkey_get_field(const Botan::Public_Key& key, std::string_view field) {
40✔
145
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
146
   // Not currently handled by get_int_field
147
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
40✔
148
      if(field == "public_x") {
15✔
149
         return Botan::BigInt::from_bytes(ecc->_public_ec_point().x_bytes());
16✔
150
      } else if(field == "public_y") {
7✔
151
         return Botan::BigInt::from_bytes(ecc->_public_ec_point().y_bytes());
12✔
152
      }
153
   }
154
#endif
155

156
   try {
26✔
157
      return key.get_int_field(field);
26✔
158
   } catch(Botan::Unknown_PK_Field_Name&) {
2✔
159
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
2✔
160
   }
2✔
161
}
162

163
Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
35✔
164
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
165
   // Not currently handled by get_int_field
166
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
35✔
167
      if(field == "public_x") {
16✔
168
         return Botan::BigInt::from_bytes(ecc->_public_ec_point().x_bytes());
4✔
169
      } else if(field == "public_y") {
14✔
170
         return Botan::BigInt::from_bytes(ecc->_public_ec_point().y_bytes());
8✔
171
      }
172
   }
173
#endif
174

175
   try {
29✔
176
      return key.get_int_field(field);
29✔
177
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
178
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
179
   }
4✔
180
}
181

182
}  // namespace
183

184
extern "C" {
185

186
using namespace Botan_FFI;
187

188
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
189
   if(field_name_cstr == nullptr) {
40✔
190
      return BOTAN_FFI_ERROR_NULL_POINTER;
191
   }
192

193
   const std::string field_name(field_name_cstr);
40✔
194

195
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
196
}
40✔
197

198
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
199
   if(field_name_cstr == nullptr) {
35✔
200
      return BOTAN_FFI_ERROR_NULL_POINTER;
201
   }
202

203
   const std::string field_name(field_name_cstr);
35✔
204

205
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
136✔
206
}
35✔
207

208
/* RSA specific operations */
209

210
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
2✔
211
   if(n_bits < 1024 || n_bits > 16 * 1024) {
2✔
212
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
213
   }
214

215
   std::string n_str = std::to_string(n_bits);
2✔
216

217
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
2✔
218
}
2✔
219

220
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✔
221
#if defined(BOTAN_HAS_RSA)
222
   if(key == nullptr) {
2✔
223
      return BOTAN_FFI_ERROR_NULL_POINTER;
224
   }
225
   *key = nullptr;
2✔
226

227
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
228
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
2✔
229
      return ffi_new_object(key, std::move(rsa));
4✔
230
   });
4✔
231
#else
232
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
233
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
234
#endif
235
}
236

237
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
238
#if defined(BOTAN_HAS_RSA)
239
   if(key == nullptr || bits == nullptr) {
1✔
240
      return BOTAN_FFI_ERROR_NULL_POINTER;
241
   }
242
   *key = nullptr;
1✔
243

244
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
245
      Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
1✔
246
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, std::span{bits, len});
1✔
247
      return ffi_new_object(key, std::move(rsa));
2✔
248
   });
2✔
249
#else
250
   BOTAN_UNUSED(key, bits, len);
251
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
252
#endif
253
}
254

255
int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e) {
4✔
256
#if defined(BOTAN_HAS_RSA)
257
   if(key == nullptr) {
4✔
258
      return BOTAN_FFI_ERROR_NULL_POINTER;
259
   }
260
   *key = nullptr;
4✔
261
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
262
      auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
4✔
263
      return ffi_new_object(key, std::move(rsa));
3✔
264
   });
7✔
265
#else
266
   BOTAN_UNUSED(key, n, e);
267
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
268
#endif
269
}
270

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

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

279
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) {
1✔
280
   return botan_privkey_get_field(n, key, "n");
1✔
281
}
282

283
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
284
   return botan_privkey_get_field(e, key, "e");
1✔
285
}
286

287
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
1✔
288
   return botan_privkey_get_field(d, key, "d");
1✔
289
}
290

291
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
292
   return botan_pubkey_get_field(e, key, "e");
1✔
293
}
294

295
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
296
   return botan_pubkey_get_field(n, key, "n");
1✔
297
}
298

299
int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
4✔
300
#if defined(BOTAN_HAS_RSA)
301
   return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
14✔
302
      if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
303
         if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
304
            return write_vec_output(out, out_len, rsa->private_key_bits());
305
         } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
306
            return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
307
         } else {
308
            return BOTAN_FFI_ERROR_BAD_FLAG;
309
         }
310
      } else {
311
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
312
      }
313
   });
314
#else
315
   BOTAN_UNUSED(rsa_key, out, out_len, flags);
316
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
317
#endif
318
}
319

320
/* DSA specific operations */
321
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
322
#if defined(BOTAN_HAS_DSA)
323

324
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
325
      return BOTAN_FFI_ERROR_NULL_POINTER;
326
   }
327

328
   if((pbits % 64 != 0) || (qbits % 8 != 0) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
329
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
330
   }
331

332
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
333
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
334
      Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
1✔
335
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
1✔
336
      return ffi_new_object(key, std::move(dsa));
1✔
337
   });
3✔
338
#else
339
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
340
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
341
#endif
342
}
343

344
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✔
345
#if defined(BOTAN_HAS_DSA)
346
   if(key == nullptr) {
2✔
347
      return BOTAN_FFI_ERROR_NULL_POINTER;
348
   }
349
   *key = nullptr;
2✔
350

351
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
352
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
353
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
2✔
354
      return ffi_new_object(key, std::move(dsa));
2✔
355
   });
6✔
356
#else
357
   BOTAN_UNUSED(key, p, q, g, x);
358
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
359
#endif
360
}
361

362
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✔
363
#if defined(BOTAN_HAS_DSA)
364
   if(key == nullptr) {
2✔
365
      return BOTAN_FFI_ERROR_NULL_POINTER;
366
   }
367
   *key = nullptr;
2✔
368

369
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
370
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
371
      auto dsa = std::make_unique<Botan::DSA_PublicKey>(group, safe_get(y));
2✔
372
      return ffi_new_object(key, std::move(dsa));
2✔
373
   });
6✔
374
#else
375
   BOTAN_UNUSED(key, p, q, g, y);
376
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
377
#endif
378
}
379

380
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
381
   return botan_privkey_get_field(x, key, "x");
2✔
382
}
383

384
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
2✔
385
   return botan_pubkey_get_field(p, key, "p");
2✔
386
}
387

388
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) {
2✔
389
   return botan_pubkey_get_field(q, key, "q");
2✔
390
}
391

392
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
393
   return botan_pubkey_get_field(g, key, "g");
2✔
394
}
395

396
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
397
   return botan_pubkey_get_field(y, key, "y");
2✔
398
}
399

400
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
401
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
402
}
403

404
/* ECDSA specific operations */
405

406
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key) {
1✔
407
#if defined(BOTAN_HAS_ECC_KEY)
408
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
409
      const Botan::Public_Key& pub_key = safe_get(key);
1✔
410
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
1✔
411

412
      if(ec_key == nullptr) {
1✔
413
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
414
      }
415

416
      return ec_key->domain().used_explicit_encoding() ? 1 : 0;
1✔
417
   });
1✔
418
#else
419
   BOTAN_UNUSED(key);
420
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
421
#endif
422
}
423

424
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
425
                            const botan_mp_t public_x,
426
                            const botan_mp_t public_y,
427
                            const char* curve_name) {
428
#if defined(BOTAN_HAS_ECDSA)
429
   if(key == nullptr || curve_name == nullptr) {
2✔
430
      return BOTAN_FFI_ERROR_NULL_POINTER;
431
   }
432
   *key = nullptr;
2✔
433

434
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
435
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
436

437
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
438
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
439
         ffi_new_object(key, std::move(p_key));
2✔
440
      }
441

442
      return rc;
2✔
443
   });
4✔
444
#else
445
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
446
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
447
#endif
448
}
449

450
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
451
#if defined(BOTAN_HAS_ECDSA)
452
   if(key == nullptr || curve_name == nullptr) {
2✔
453
      return BOTAN_FFI_ERROR_NULL_POINTER;
454
   }
455
   *key = nullptr;
2✔
456

457
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
458
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
2✔
459
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
2✔
460
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
461
         ffi_new_object(key, std::move(p_key));
4✔
462
      }
463
      return rc;
2✔
464
   });
4✔
465
#else
466
   BOTAN_UNUSED(key, scalar, curve_name);
467
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
468
#endif
469
}
470

471
/* ElGamal specific operations */
472
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
473
#if defined(BOTAN_HAS_ELGAMAL)
474
   if(key == nullptr || rng_obj == nullptr) {
1✔
475
      return BOTAN_FFI_ERROR_NULL_POINTER;
476
   }
477
   *key = nullptr;
1✔
478

479
   if(pbits < 1024 || qbits < 160) {
1✔
480
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
481
   }
482

483
   Botan::DL_Group::PrimeType prime_type =
1✔
484
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
485

486
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
487
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
488
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
489
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
490
      return ffi_new_object(key, std::move(elg));
1✔
491
   });
3✔
492
#else
493
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
494
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
495
#endif
496
}
497

498
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
2✔
499
#if defined(BOTAN_HAS_ELGAMAL)
500
   if(key == nullptr) {
2✔
501
      return BOTAN_FFI_ERROR_NULL_POINTER;
502
   }
503
   *key = nullptr;
2✔
504
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
505
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
506
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
2✔
507
      return ffi_new_object(key, std::move(elg));
2✔
508
   });
6✔
509
#else
510
   BOTAN_UNUSED(key, p, g, y);
511
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
512
#endif
513
}
514

515
int botan_privkey_load_elgamal(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
2✔
516
#if defined(BOTAN_HAS_ELGAMAL)
517
   if(key == nullptr) {
2✔
518
      return BOTAN_FFI_ERROR_NULL_POINTER;
519
   }
520
   *key = nullptr;
2✔
521
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
522
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
523
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(group, safe_get(x));
2✔
524
      return ffi_new_object(key, std::move(elg));
2✔
525
   });
6✔
526
#else
527
   BOTAN_UNUSED(key, p, g, x);
528
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
529
#endif
530
}
531

532
/* Diffie Hellman specific operations */
533

534
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
535
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
536
}
537

538
int botan_privkey_load_dh(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
1✔
539
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
540
   if(key == nullptr) {
1✔
541
      return BOTAN_FFI_ERROR_NULL_POINTER;
542
   }
543
   *key = nullptr;
1✔
544
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
545
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
546
      auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
1✔
547
      return ffi_new_object(key, std::move(dh));
1✔
548
   });
3✔
549
#else
550
   BOTAN_UNUSED(key, p, g, x);
551
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
552
#endif
553
}
554

555
int botan_pubkey_load_dh(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
1✔
556
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
557
   if(key == nullptr) {
1✔
558
      return BOTAN_FFI_ERROR_NULL_POINTER;
559
   }
560
   *key = nullptr;
1✔
561
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
562
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
563
      auto dh = std::make_unique<Botan::DH_PublicKey>(group, safe_get(y));
1✔
564
      return ffi_new_object(key, std::move(dh));
1✔
565
   });
3✔
566
#else
567
   BOTAN_UNUSED(key, p, g, y);
568
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
569
#endif
570
}
571

572
/* ECDH + x25519/x448 specific operations */
573

574
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
575
   if(key_obj == nullptr || param_str == nullptr) {
2✔
576
      return BOTAN_FFI_ERROR_NULL_POINTER;
577
   }
578
   *key_obj = nullptr;
2✔
579

580
   const std::string params(param_str);
2✔
581

582
   if(params == "X25519" || params == "x25519" || params == "curve25519") {
2✔
583
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
584
   }
585

586
   if(params == "X448" || params == "x448") {
2✔
587
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
588
   }
589

590
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
591
}
2✔
592

593
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
594
                           const botan_mp_t public_x,
595
                           const botan_mp_t public_y,
596
                           const char* curve_name) {
597
#if defined(BOTAN_HAS_ECDH)
598
   if(key == nullptr || curve_name == nullptr) {
1✔
599
      return BOTAN_FFI_ERROR_NULL_POINTER;
600
   }
601
   *key = nullptr;
1✔
602
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
603
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
604
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
605

606
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
607
         ffi_new_object(key, std::move(p_key));
1✔
608
      }
609
      return rc;
1✔
610
   });
2✔
611
#else
612
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
613
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
614
#endif
615
}
616

617
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
4✔
618
#if defined(BOTAN_HAS_ECDH)
619
   if(key == nullptr || curve_name == nullptr) {
4✔
620
      return BOTAN_FFI_ERROR_NULL_POINTER;
621
   }
622
   *key = nullptr;
4✔
623
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
624
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
4✔
625
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
4✔
626
      if(rc == BOTAN_FFI_SUCCESS) {
4✔
627
         ffi_new_object(key, std::move(p_key));
8✔
628
      }
629
      return rc;
4✔
630
   });
8✔
631
#else
632
   BOTAN_UNUSED(key, scalar, curve_name);
633
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
634
#endif
635
}
636

637
/* SM2 specific operations */
638

639
int botan_pubkey_sm2_compute_za(
2✔
640
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
641
   if(out == nullptr || out_len == nullptr || ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
642
      return BOTAN_FFI_ERROR_NULL_POINTER;
643
   }
644

645
#if defined(BOTAN_HAS_SM2)
646
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
647
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
648
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
649

650
      if(ec_key == nullptr) {
2✔
651
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
652
      }
653

654
      if(ec_key->algo_name() != "SM2") {
2✔
655
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
656
      }
657

658
      const std::string ident_str(ident);
2✔
659
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
660

661
      const auto& pt = ec_key->_public_ec_point();
2✔
662

663
      const auto za = Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), pt);
2✔
664

665
      return write_vec_output(out, out_len, za);
2✔
666
   });
6✔
667
#else
668
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
669
#endif
670
}
671

672
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
673
                          const botan_mp_t public_x,
674
                          const botan_mp_t public_y,
675
                          const char* curve_name) {
676
#if defined(BOTAN_HAS_SM2)
677
   if(key == nullptr || curve_name == nullptr) {
3✔
678
      return BOTAN_FFI_ERROR_NULL_POINTER;
679
   }
680
   *key = nullptr;
3✔
681

682
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
683
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
3✔
684
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
3✔
685
         return ffi_new_object(key, std::move(p_key));
3✔
686
      } else {
687
         return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
688
      }
689
   });
6✔
690
#else
691
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
692
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
693
#endif
694
}
695

696
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
697
#if defined(BOTAN_HAS_SM2)
698
   if(key == nullptr || curve_name == nullptr) {
3✔
699
      return BOTAN_FFI_ERROR_NULL_POINTER;
700
   }
701
   *key = nullptr;
3✔
702

703
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
704
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
705
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
706

707
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
708
         ffi_new_object(key, std::move(p_key));
6✔
709
      }
710
      return rc;
3✔
711
   });
6✔
712
#else
713
   BOTAN_UNUSED(key, scalar, curve_name);
714
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
715
#endif
716
}
717

718
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
719
                              const botan_mp_t public_x,
720
                              const botan_mp_t public_y,
721
                              const char* curve_name) {
722
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
723
}
724

725
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
726
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
727
}
728

729
/* Ed25519 specific operations */
730

731
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
732
#if defined(BOTAN_HAS_ED25519)
733
   if(key == nullptr) {
1✔
734
      return BOTAN_FFI_ERROR_NULL_POINTER;
735
   }
736
   *key = nullptr;
1✔
737
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
738
      auto ed25519 =
1✔
739
         std::make_unique<Botan::Ed25519_PrivateKey>(Botan::Ed25519_PrivateKey::from_seed(std::span{privkey, 32}));
2✔
740
      return ffi_new_object(key, std::move(ed25519));
2✔
741
   });
2✔
742
#else
743
   BOTAN_UNUSED(key, privkey);
744
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
745
#endif
746
}
747

748
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
749
#if defined(BOTAN_HAS_ED25519)
750
   if(key == nullptr) {
1✔
751
      return BOTAN_FFI_ERROR_NULL_POINTER;
752
   }
753
   *key = nullptr;
1✔
754
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
755
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
756
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
757
      return ffi_new_object(key, std::move(ed25519));
1✔
758
   });
3✔
759
#else
760
   BOTAN_UNUSED(key, pubkey);
761
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
762
#endif
763
}
764

765
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
766
#if defined(BOTAN_HAS_ED25519)
767
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
768
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
769
         const auto ed_key = ed->raw_private_key_bits();
770
         if(ed_key.size() != 64) {
771
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
772
         }
773
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
774
         return BOTAN_FFI_SUCCESS;
775
      } else {
776
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
777
      }
778
   });
779
#else
780
   BOTAN_UNUSED(key, output);
781
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
782
#endif
783
}
784

785
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
786
#if defined(BOTAN_HAS_ED25519)
787
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
788
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
789
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
790
         if(ed_key.size() != 32) {
791
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
792
         }
793
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
794
         return BOTAN_FFI_SUCCESS;
795
      } else {
796
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
797
      }
798
   });
799
#else
800
   BOTAN_UNUSED(key, output);
801
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
802
#endif
803
}
804

805
/* Ed448 specific operations */
806

807
int botan_privkey_load_ed448(botan_privkey_t* key, const uint8_t privkey[57]) {
1✔
808
#if defined(BOTAN_HAS_ED448)
809
   if(key == nullptr) {
1✔
810
      return BOTAN_FFI_ERROR_NULL_POINTER;
811
   }
812
   *key = nullptr;
1✔
813
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
814
      auto ed448 = std::make_unique<Botan::Ed448_PrivateKey>(std::span(privkey, 57));
1✔
815
      return ffi_new_object(key, std::move(ed448));
2✔
816
   });
2✔
817
#else
818
   BOTAN_UNUSED(key, privkey);
819
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
820
#endif
821
}
822

823
int botan_pubkey_load_ed448(botan_pubkey_t* key, const uint8_t pubkey[57]) {
1✔
824
#if defined(BOTAN_HAS_ED448)
825
   if(key == nullptr) {
1✔
826
      return BOTAN_FFI_ERROR_NULL_POINTER;
827
   }
828
   *key = nullptr;
1✔
829
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
830
      auto ed448 = std::make_unique<Botan::Ed448_PublicKey>(std::span(pubkey, 57));
1✔
831
      return ffi_new_object(key, std::move(ed448));
1✔
832
   });
2✔
833
#else
834
   BOTAN_UNUSED(key, pubkey);
835
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
836
#endif
837
}
838

839
int botan_privkey_ed448_get_privkey(botan_privkey_t key, uint8_t output[57]) {
1✔
840
#if defined(BOTAN_HAS_ED448)
841
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
842
      if(auto ed = dynamic_cast<const Botan::Ed448_PrivateKey*>(&k)) {
843
         const auto ed_key = ed->raw_private_key_bits();
844
         Botan::copy_mem(std::span(output, 57), ed_key);
845
         return BOTAN_FFI_SUCCESS;
846
      } else {
847
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
848
      }
849
   });
850
#else
851
   BOTAN_UNUSED(key, output);
852
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
853
#endif
854
}
855

856
int botan_pubkey_ed448_get_pubkey(botan_pubkey_t key, uint8_t output[57]) {
1✔
857
#if defined(BOTAN_HAS_ED448)
858
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
3✔
859
      if(auto ed = dynamic_cast<const Botan::Ed448_PublicKey*>(&k)) {
860
         const auto ed_key = ed->public_key_bits();
861
         Botan::copy_mem(std::span(output, 57), ed_key);
862
         return BOTAN_FFI_SUCCESS;
863
      } else {
864
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
865
      }
866
   });
867
#else
868
   BOTAN_UNUSED(key, output);
869
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
870
#endif
871
}
872

873
/* X25519 specific operations */
874

875
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
876
#if defined(BOTAN_HAS_X25519)
877
   if(key == nullptr) {
1✔
878
      return BOTAN_FFI_ERROR_NULL_POINTER;
879
   }
880
   *key = nullptr;
1✔
881
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
882
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(std::span{privkey, 32});
1✔
883
      return ffi_new_object(key, std::move(x25519));
2✔
884
   });
2✔
885
#else
886
   BOTAN_UNUSED(key, privkey);
887
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
888
#endif
889
}
890

891
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
892
#if defined(BOTAN_HAS_X25519)
893
   if(key == nullptr) {
1✔
894
      return BOTAN_FFI_ERROR_NULL_POINTER;
895
   }
896
   *key = nullptr;
1✔
897
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
898
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(std::span{pubkey, 32});
1✔
899
      return ffi_new_object(key, std::move(x25519));
1✔
900
   });
2✔
901
#else
902
   BOTAN_UNUSED(key, pubkey);
903
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
904
#endif
905
}
906

907
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
908
#if defined(BOTAN_HAS_X25519)
909
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
910
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
911
         const auto x25519_key = x25519->raw_private_key_bits();
912
         if(x25519_key.size() != 32) {
913
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
914
         }
915
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
916
         return BOTAN_FFI_SUCCESS;
917
      } else {
918
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
919
      }
920
   });
921
#else
922
   BOTAN_UNUSED(key, output);
923
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
924
#endif
925
}
926

927
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
928
#if defined(BOTAN_HAS_X25519)
929
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
6✔
930
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
931
         Botan::copy_mem(std::span{output, 32}, x25519->raw_public_key_bits());
932
         return BOTAN_FFI_SUCCESS;
933
      } else {
934
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
935
      }
936
   });
937
#else
938
   BOTAN_UNUSED(key, output);
939
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
940
#endif
941
}
942

943
/* X448 specific operations */
944

945
int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
1✔
946
#if defined(BOTAN_HAS_X448)
947
   if(key == nullptr) {
1✔
948
      return BOTAN_FFI_ERROR_NULL_POINTER;
949
   }
950
   *key = nullptr;
1✔
951
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
952
      auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span{privkey, 56});
1✔
953
      return ffi_new_object(key, std::move(x448));
2✔
954
   });
2✔
955
#else
956
   BOTAN_UNUSED(key, privkey);
957
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
958
#endif
959
}
960

961
int botan_pubkey_load_x448(botan_pubkey_t* key, const uint8_t pubkey[56]) {
1✔
962
#if defined(BOTAN_HAS_X448)
963
   if(key == nullptr) {
1✔
964
      return BOTAN_FFI_ERROR_NULL_POINTER;
965
   }
966
   *key = nullptr;
1✔
967
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
968
      auto x448 = std::make_unique<Botan::X448_PublicKey>(std::span{pubkey, 56});
1✔
969
      return ffi_new_object(key, std::move(x448));
1✔
970
   });
2✔
971
#else
972
   BOTAN_UNUSED(key, pubkey);
973
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
974
#endif
975
}
976

977
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56]) {
1✔
978
#if defined(BOTAN_HAS_X448)
979
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
980
      if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
981
         const auto x448_key = x448->raw_private_key_bits();
982
         Botan::copy_mem(std::span{output, 56}, x448_key);
983
         return BOTAN_FFI_SUCCESS;
984
      } else {
985
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
986
      }
987
   });
988
#else
989
   BOTAN_UNUSED(key, output);
990
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
991
#endif
992
}
993

994
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
2✔
995
#if defined(BOTAN_HAS_X448)
996
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
6✔
997
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
998
         Botan::copy_mem(std::span{output, 56}, x448->raw_public_key_bits());
999
         return BOTAN_FFI_SUCCESS;
1000
      } else {
1001
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1002
      }
1003
   });
1004
#else
1005
   BOTAN_UNUSED(key, output);
1006
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1007
#endif
1008
}
1009

1010
/*
1011
* Algorithm specific key operations: Kyber
1012
*/
1013

1014
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
1015
#if defined(BOTAN_HAS_KYBER)
1016
   if(key == nullptr) {
4✔
1017
      return BOTAN_FFI_ERROR_NULL_POINTER;
1018
   }
1019
   *key = nullptr;
4✔
1020

1021
   const auto mode = [](size_t len) -> std::optional<Botan::KyberMode> {
12✔
1022
      if(len == 1632) {
4✔
1023
         return Botan::KyberMode::Kyber512_R3;
1✔
1024
      } else if(len == 2400) {
3✔
1025
         return Botan::KyberMode::Kyber768_R3;
2✔
1026
      } else if(len == 3168) {
1✔
1027
         return Botan::KyberMode::Kyber1024_R3;
1✔
1028
      } else {
1029
         return {};
×
1030
      }
1031
   }(key_len);
4✔
1032

1033
   if(mode.has_value()) {
4✔
1034
      return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1035
         auto kyber = std::make_unique<Botan::Kyber_PrivateKey>(std::span{privkey, key_len}, *mode);
4✔
1036
         return ffi_new_object(key, std::move(kyber));
8✔
1037
      });
4✔
1038
   } else {
1039
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
1040
   }
1041
#else
1042
   BOTAN_UNUSED(key, key_len, privkey);
1043
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1044
#endif
1045
}
1046

1047
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
1048
#if defined(BOTAN_HAS_KYBER)
1049
   if(key == nullptr) {
4✔
1050
      return BOTAN_FFI_ERROR_NULL_POINTER;
1051
   }
1052
   *key = nullptr;
4✔
1053

1054
   const auto mode = [](size_t len) -> std::optional<Botan::KyberMode> {
12✔
1055
      if(len == 800) {
4✔
1056
         return Botan::KyberMode::Kyber512_R3;
1✔
1057
      } else if(len == 1184) {
3✔
1058
         return Botan::KyberMode::Kyber768_R3;
2✔
1059
      } else if(len == 1568) {
1✔
1060
         return Botan::KyberMode::Kyber1024_R3;
1✔
1061
      } else {
1062
         return {};
×
1063
      }
1064
   }(key_len);
4✔
1065

1066
   if(mode.has_value()) {
4✔
1067
      auto kyber = std::make_unique<Botan::Kyber_PublicKey>(std::span{pubkey, key_len}, *mode);
4✔
1068
      return ffi_new_object(key, std::move(kyber));
4✔
1069
   } else {
4✔
1070
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
1071
   }
1072
#else
1073
   BOTAN_UNUSED(key, pubkey, key_len);
1074
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1075
#endif
1076
}
1077

1078
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1079
#if defined(BOTAN_HAS_KYBER)
1080
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
16✔
1081
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1082
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1083
      } else {
1084
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1085
      }
1086
   });
1087
#else
1088
   BOTAN_UNUSED(key, ctx, view);
1089
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1090
#endif
1091
}
1092

1093
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1094
#if defined(BOTAN_HAS_KYBER)
1095
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
32✔
1096
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1097
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1098
      } else {
1099
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1100
      }
1101
   });
1102
#else
1103
   BOTAN_UNUSED(key, ctx, view);
1104
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1105
#endif
1106
}
1107

1108
/*
1109
* Algorithm specific key operations: ML-KEM
1110
*/
1111

1112
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1113
#if defined(BOTAN_HAS_ML_KEM)
1114
   if(key == nullptr || privkey == nullptr || mlkem_mode == nullptr) {
4✔
1115
      return BOTAN_FFI_ERROR_NULL_POINTER;
1116
   }
1117

1118
   *key = nullptr;
4✔
1119

1120
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1121
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1122
      if(!mode.is_ml_kem()) {
4✔
1123
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1124
      }
1125

1126
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1127
      return ffi_new_object(key, std::move(mlkem_key));
4✔
1128
   });
8✔
1129
#else
1130
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1131
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1132
#endif
1133
}
1134

1135
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
4✔
1136
#if defined(BOTAN_HAS_ML_KEM)
1137
   if(key == nullptr || pubkey == nullptr || mlkem_mode == nullptr) {
4✔
1138
      return BOTAN_FFI_ERROR_NULL_POINTER;
1139
   }
1140

1141
   *key = nullptr;
4✔
1142

1143
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1144
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1145
      if(!mode.is_ml_kem()) {
4✔
1146
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1147
      }
1148

1149
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PublicKey>(std::span{pubkey, key_len}, mode.mode());
4✔
1150
      return ffi_new_object(key, std::move(mlkem_key));
4✔
1151
   });
8✔
1152
#else
1153
   BOTAN_UNUSED(key, key_len, pubkey, mlkem_mode);
1154
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1155
#endif
1156
}
1157

1158
/*
1159
* Algorithm specific key operations: ML-DSA
1160
*/
1161

1162
int botan_privkey_load_ml_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mldsa_mode) {
4✔
1163
#if defined(BOTAN_HAS_ML_DSA)
1164
   if(key == nullptr || privkey == nullptr || mldsa_mode == nullptr) {
4✔
1165
      return BOTAN_FFI_ERROR_NULL_POINTER;
1166
   }
1167

1168
   *key = nullptr;
4✔
1169

1170
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1171
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1172
      if(!mode.is_ml_dsa()) {
4✔
1173
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1174
      }
1175

1176
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1177
      return ffi_new_object(key, std::move(mldsa_key));
4✔
1178
   });
8✔
1179
#else
1180
   BOTAN_UNUSED(key, key_len, privkey, mldsa_mode);
1181
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1182
#endif
1183
}
1184

1185
int botan_pubkey_load_ml_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mldsa_mode) {
4✔
1186
#if defined(BOTAN_HAS_ML_DSA)
1187
   if(key == nullptr || pubkey == nullptr || mldsa_mode == nullptr) {
4✔
1188
      return BOTAN_FFI_ERROR_NULL_POINTER;
1189
   }
1190

1191
   *key = nullptr;
4✔
1192

1193
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1194
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1195
      if(!mode.is_ml_dsa()) {
4✔
1196
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1197
      }
1198

1199
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
4✔
1200
      return ffi_new_object(key, std::move(mldsa_key));
4✔
1201
   });
8✔
1202
#else
1203
   BOTAN_UNUSED(key, key_len, pubkey, mldsa_mode);
1204
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1205
#endif
1206
}
1207

1208
/*
1209
* Algorithm specific key operations: SLH-DSA
1210
*/
1211

1212
int botan_privkey_load_slh_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1213
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1214
   if(key == nullptr || privkey == nullptr || slhdsa_mode == nullptr) {
13✔
1215
      return BOTAN_FFI_ERROR_NULL_POINTER;
1216
   }
1217

1218
   *key = nullptr;
13✔
1219

1220
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1221
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1222
      if(!mode.is_slh_dsa()) {
13✔
1223
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1224
      }
1225

1226
      auto slhdsa_key = std::make_unique<Botan::SLH_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1227
      return ffi_new_object(key, std::move(slhdsa_key));
13✔
1228
   });
26✔
1229
#else
1230
   BOTAN_UNUSED(key, key_len, privkey, slhdsa_mode);
1231
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1232
#endif
1233
}
1234

1235
int botan_pubkey_load_slh_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1236
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1237
   if(key == nullptr || pubkey == nullptr || slhdsa_mode == nullptr) {
13✔
1238
      return BOTAN_FFI_ERROR_NULL_POINTER;
1239
   }
1240

1241
   *key = nullptr;
13✔
1242

1243
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1244
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1245
      if(!mode.is_slh_dsa()) {
13✔
1246
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1247
      }
1248

1249
      auto mldsa_key = std::make_unique<Botan::SLH_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1250
      return ffi_new_object(key, std::move(mldsa_key));
13✔
1251
   });
26✔
1252
#else
1253
   BOTAN_UNUSED(key, key_len, pubkey, slhdsa_mode);
1254
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1255
#endif
1256
}
1257

1258
/*
1259
* Algorithm specific key operations: FrodoKEM
1260
*/
1261

1262
int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* frodo_mode) {
13✔
1263
#if defined(BOTAN_HAS_FRODOKEM)
1264
   if(key == nullptr || privkey == nullptr || frodo_mode == nullptr) {
13✔
1265
      return BOTAN_FFI_ERROR_NULL_POINTER;
1266
   }
1267

1268
   *key = nullptr;
13✔
1269

1270
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1271
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1272
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1273
      return ffi_new_object(key, std::move(frodo_key));
26✔
1274
   });
26✔
1275
#else
1276
   BOTAN_UNUSED(key, privkey, key_len, frodo_mode);
1277
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1278
#endif
1279
}
1280

1281
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode) {
13✔
1282
#if defined(BOTAN_HAS_FRODOKEM)
1283
   if(key == nullptr || pubkey == nullptr || frodo_mode == nullptr) {
13✔
1284
      return BOTAN_FFI_ERROR_NULL_POINTER;
1285
   }
1286

1287
   *key = nullptr;
13✔
1288

1289
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1290
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1291
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1292
      return ffi_new_object(key, std::move(frodo_key));
13✔
1293
   });
26✔
1294
#else
1295
   BOTAN_UNUSED(key, pubkey, key_len, frodo_mode);
1296
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1297
#endif
1298
}
1299

1300
/*
1301
* Algorithm specific key operations : Classic McEliece
1302
*/
1303

1304
int botan_privkey_load_classic_mceliece(botan_privkey_t* key,
17✔
1305
                                        const uint8_t privkey[],
1306
                                        size_t key_len,
1307
                                        const char* cmce_mode) {
1308
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1309
   if(key == nullptr || privkey == nullptr || cmce_mode == nullptr) {
17✔
1310
      return BOTAN_FFI_ERROR_NULL_POINTER;
1311
   }
1312

1313
   *key = nullptr;
17✔
1314

1315
   return ffi_guard_thunk(__func__, [=]() -> int {
17✔
1316
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1317
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PrivateKey>(std::span{privkey, key_len}, mode);
17✔
1318
      return ffi_new_object(key, std::move(cmce_key));
34✔
1319
   });
34✔
1320
#else
1321
   BOTAN_UNUSED(key, privkey, key_len, cmce_mode);
1322
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1323
#endif
1324
}
1325

1326
int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
17✔
1327
                                       const uint8_t pubkey[],
1328
                                       size_t key_len,
1329
                                       const char* cmce_mode) {
1330
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1331
   if(key == nullptr || pubkey == nullptr || cmce_mode == nullptr) {
17✔
1332
      return BOTAN_FFI_ERROR_NULL_POINTER;
1333
   }
1334

1335
   *key = nullptr;
17✔
1336

1337
   return ffi_guard_thunk(__func__, [=]() -> int {
17✔
1338
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1339
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PublicKey>(std::span{pubkey, key_len}, mode);
17✔
1340
      return ffi_new_object(key, std::move(cmce_key));
17✔
1341
   });
34✔
1342
#else
1343
   BOTAN_UNUSED(key, pubkey, key_len, cmce_mode);
1344
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1345
#endif
1346
}
1347

1348
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1349
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1350
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1351
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1352
         auto pt = ecc->_public_ec_point().serialize_uncompressed();
1353
         return invoke_view_callback(view, ctx, pt);
1354
      } else {
1355
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1356
      }
1357
   });
1358
#else
1359
   BOTAN_UNUSED(key, view, ctx);
1360
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1361
#endif
1362
}
1363

1364
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1365
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1366
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1367
}
1✔
1368

1369
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1370
                         const char* aead,
1371
                         const uint8_t ct[],
1372
                         size_t ct_len,
1373
                         const uint8_t ad[],
1374
                         size_t ad_len,
1375
                         uint8_t out[],
1376
                         size_t* out_len) {
1377
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1378
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1379
}
1380

1381
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1382
                         botan_rng_t rng_obj,
1383
                         const char* aead,
1384
                         const uint8_t pt[],
1385
                         size_t pt_len,
1386
                         const uint8_t ad[],
1387
                         size_t ad_len,
1388
                         uint8_t out[],
1389
                         size_t* out_len) {
1390
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1391
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1392
}
1393
}
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