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

randombit / botan / 16399928974

20 Jul 2025 12:32PM UTC coverage: 90.633% (-0.004%) from 90.637%
16399928974

push

github

web-flow
Merge pull request #5005 from randombit/jack/enable-clang-tidy-misc-misplaced-const

Enable clang-tidy warning misc-misplaced-const

99937 of 110266 relevant lines covered (90.63%)

12268307.92 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
            // TODO define new generic functions for this
307
            return write_str_output(reinterpret_cast<char*>(out),
308
                                    out_len,
309
                                    Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
310
         } else {
311
            return BOTAN_FFI_ERROR_BAD_FLAG;
312
         }
313
      } else {
314
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
315
      }
316
   });
317
#else
318
   BOTAN_UNUSED(rsa_key, out, out_len, flags);
319
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
320
#endif
321
}
322

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

327
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
328
      return BOTAN_FFI_ERROR_NULL_POINTER;
329
   }
330

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

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

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

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

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

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

383
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
384
   return botan_privkey_get_field(x, key, "x");
2✔
385
}
386

387
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
2✔
388
   return botan_pubkey_get_field(p, key, "p");
2✔
389
}
390

391
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) {
2✔
392
   return botan_pubkey_get_field(q, key, "q");
2✔
393
}
394

395
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
396
   return botan_pubkey_get_field(g, key, "g");
2✔
397
}
398

399
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
400
   return botan_pubkey_get_field(y, key, "y");
2✔
401
}
402

403
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
404
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
405
}
406

407
/* ECDSA specific operations */
408

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

415
      if(ec_key == nullptr) {
1✔
416
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
417
      }
418

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

427
// NOLINTBEGIN(misc-misplaced-const)
428

429
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
430
                            const botan_mp_t public_x,
431
                            const botan_mp_t public_y,
432
                            const char* curve_name) {
433
#if defined(BOTAN_HAS_ECDSA)
434
   if(key == nullptr || curve_name == nullptr) {
2✔
435
      return BOTAN_FFI_ERROR_NULL_POINTER;
436
   }
437
   *key = nullptr;
2✔
438

439
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
440
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
441

442
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
443
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
444
         ffi_new_object(key, std::move(p_key));
2✔
445
      }
446

447
      return rc;
2✔
448
   });
4✔
449
#else
450
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
451
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
452
#endif
453
}
454

455
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
456
#if defined(BOTAN_HAS_ECDSA)
457
   if(key == nullptr || curve_name == nullptr) {
2✔
458
      return BOTAN_FFI_ERROR_NULL_POINTER;
459
   }
460
   *key = nullptr;
2✔
461

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

476
/* ElGamal specific operations */
477
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
478
#if defined(BOTAN_HAS_ELGAMAL)
479
   if(key == nullptr || rng_obj == nullptr) {
1✔
480
      return BOTAN_FFI_ERROR_NULL_POINTER;
481
   }
482
   *key = nullptr;
1✔
483

484
   if(pbits < 1024 || qbits < 160) {
1✔
485
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
486
   }
487

488
   Botan::DL_Group::PrimeType prime_type =
1✔
489
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
490

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

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

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

537
/* Diffie Hellman specific operations */
538

539
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
540
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
541
}
542

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

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

577
/* ECDH + x25519/x448 specific operations */
578

579
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
580
   if(key_obj == nullptr || param_str == nullptr) {
2✔
581
      return BOTAN_FFI_ERROR_NULL_POINTER;
582
   }
583
   *key_obj = nullptr;
2✔
584

585
   const std::string params(param_str);
2✔
586

587
   if(params == "X25519" || params == "x25519" || params == "curve25519") {
2✔
588
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
589
   }
590

591
   if(params == "X448" || params == "x448") {
2✔
592
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
593
   }
594

595
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
596
}
2✔
597

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

611
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
612
         ffi_new_object(key, std::move(p_key));
1✔
613
      }
614
      return rc;
1✔
615
   });
2✔
616
#else
617
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
618
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
619
#endif
620
}
621

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

642
/* SM2 specific operations */
643

644
int botan_pubkey_sm2_compute_za(
2✔
645
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
646
   if(out == nullptr || out_len == nullptr || ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
647
      return BOTAN_FFI_ERROR_NULL_POINTER;
648
   }
649

650
#if defined(BOTAN_HAS_SM2)
651
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
652
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
653
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
654

655
      if(ec_key == nullptr) {
2✔
656
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
657
      }
658

659
      if(ec_key->algo_name() != "SM2") {
2✔
660
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
661
      }
662

663
      const std::string ident_str(ident);
2✔
664
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
665

666
      const auto& pt = ec_key->_public_ec_point();
2✔
667

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

670
      return write_vec_output(out, out_len, za);
2✔
671
   });
6✔
672
#else
673
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
674
#endif
675
}
676

677
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
678
                          const botan_mp_t public_x,
679
                          const botan_mp_t public_y,
680
                          const char* curve_name) {
681
#if defined(BOTAN_HAS_SM2)
682
   if(key == nullptr || curve_name == nullptr) {
3✔
683
      return BOTAN_FFI_ERROR_NULL_POINTER;
684
   }
685
   *key = nullptr;
3✔
686

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

701
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
702
#if defined(BOTAN_HAS_SM2)
703
   if(key == nullptr || curve_name == nullptr) {
3✔
704
      return BOTAN_FFI_ERROR_NULL_POINTER;
705
   }
706
   *key = nullptr;
3✔
707

708
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
709
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
710
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
711

712
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
713
         ffi_new_object(key, std::move(p_key));
6✔
714
      }
715
      return rc;
3✔
716
   });
6✔
717
#else
718
   BOTAN_UNUSED(key, scalar, curve_name);
719
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
720
#endif
721
}
722

723
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
724
                              const botan_mp_t public_x,
725
                              const botan_mp_t public_y,
726
                              const char* curve_name) {
727
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
728
}
729

730
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
731
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
732
}
733

734
/* Ed25519 specific operations */
735

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

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

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

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

810
/* Ed448 specific operations */
811

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

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

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

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

878
/* X25519 specific operations */
879

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

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

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

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

948
/* X448 specific operations */
949

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

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

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

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

1015
/*
1016
* Algorithm specific key operations: Kyber
1017
*/
1018

1019
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
1020
#if defined(BOTAN_HAS_KYBER)
1021
   if(key == nullptr) {
4✔
1022
      return BOTAN_FFI_ERROR_NULL_POINTER;
1023
   }
1024
   *key = nullptr;
4✔
1025

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

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

1052
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
1053
#if defined(BOTAN_HAS_KYBER)
1054
   if(key == nullptr) {
4✔
1055
      return BOTAN_FFI_ERROR_NULL_POINTER;
1056
   }
1057
   *key = nullptr;
4✔
1058

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

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

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

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

1113
/*
1114
* Algorithm specific key operations: ML-KEM
1115
*/
1116

1117
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1118
#if defined(BOTAN_HAS_ML_KEM)
1119
   if(key == nullptr || privkey == nullptr || mlkem_mode == nullptr) {
4✔
1120
      return BOTAN_FFI_ERROR_NULL_POINTER;
1121
   }
1122

1123
   *key = nullptr;
4✔
1124

1125
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1126
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1127
      if(!mode.is_ml_kem()) {
4✔
1128
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1129
      }
1130

1131
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1132
      return ffi_new_object(key, std::move(mlkem_key));
4✔
1133
   });
8✔
1134
#else
1135
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1136
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1137
#endif
1138
}
1139

1140
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
4✔
1141
#if defined(BOTAN_HAS_ML_KEM)
1142
   if(key == nullptr || pubkey == nullptr || mlkem_mode == nullptr) {
4✔
1143
      return BOTAN_FFI_ERROR_NULL_POINTER;
1144
   }
1145

1146
   *key = nullptr;
4✔
1147

1148
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1149
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1150
      if(!mode.is_ml_kem()) {
4✔
1151
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1152
      }
1153

1154
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PublicKey>(std::span{pubkey, key_len}, mode.mode());
4✔
1155
      return ffi_new_object(key, std::move(mlkem_key));
4✔
1156
   });
8✔
1157
#else
1158
   BOTAN_UNUSED(key, key_len, pubkey, mlkem_mode);
1159
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1160
#endif
1161
}
1162

1163
/*
1164
* Algorithm specific key operations: ML-DSA
1165
*/
1166

1167
int botan_privkey_load_ml_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mldsa_mode) {
4✔
1168
#if defined(BOTAN_HAS_ML_DSA)
1169
   if(key == nullptr || privkey == nullptr || mldsa_mode == nullptr) {
4✔
1170
      return BOTAN_FFI_ERROR_NULL_POINTER;
1171
   }
1172

1173
   *key = nullptr;
4✔
1174

1175
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1176
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1177
      if(!mode.is_ml_dsa()) {
4✔
1178
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1179
      }
1180

1181
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1182
      return ffi_new_object(key, std::move(mldsa_key));
4✔
1183
   });
8✔
1184
#else
1185
   BOTAN_UNUSED(key, key_len, privkey, mldsa_mode);
1186
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1187
#endif
1188
}
1189

1190
int botan_pubkey_load_ml_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mldsa_mode) {
4✔
1191
#if defined(BOTAN_HAS_ML_DSA)
1192
   if(key == nullptr || pubkey == nullptr || mldsa_mode == nullptr) {
4✔
1193
      return BOTAN_FFI_ERROR_NULL_POINTER;
1194
   }
1195

1196
   *key = nullptr;
4✔
1197

1198
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1199
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1200
      if(!mode.is_ml_dsa()) {
4✔
1201
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1202
      }
1203

1204
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
4✔
1205
      return ffi_new_object(key, std::move(mldsa_key));
4✔
1206
   });
8✔
1207
#else
1208
   BOTAN_UNUSED(key, key_len, pubkey, mldsa_mode);
1209
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1210
#endif
1211
}
1212

1213
/*
1214
* Algorithm specific key operations: SLH-DSA
1215
*/
1216

1217
int botan_privkey_load_slh_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1218
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1219
   if(key == nullptr || privkey == nullptr || slhdsa_mode == nullptr) {
13✔
1220
      return BOTAN_FFI_ERROR_NULL_POINTER;
1221
   }
1222

1223
   *key = nullptr;
13✔
1224

1225
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1226
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1227
      if(!mode.is_slh_dsa()) {
13✔
1228
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1229
      }
1230

1231
      auto slhdsa_key = std::make_unique<Botan::SLH_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1232
      return ffi_new_object(key, std::move(slhdsa_key));
13✔
1233
   });
26✔
1234
#else
1235
   BOTAN_UNUSED(key, key_len, privkey, slhdsa_mode);
1236
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1237
#endif
1238
}
1239

1240
int botan_pubkey_load_slh_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1241
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1242
   if(key == nullptr || pubkey == nullptr || slhdsa_mode == nullptr) {
13✔
1243
      return BOTAN_FFI_ERROR_NULL_POINTER;
1244
   }
1245

1246
   *key = nullptr;
13✔
1247

1248
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1249
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1250
      if(!mode.is_slh_dsa()) {
13✔
1251
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1252
      }
1253

1254
      auto mldsa_key = std::make_unique<Botan::SLH_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1255
      return ffi_new_object(key, std::move(mldsa_key));
13✔
1256
   });
26✔
1257
#else
1258
   BOTAN_UNUSED(key, key_len, pubkey, slhdsa_mode);
1259
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1260
#endif
1261
}
1262

1263
/*
1264
* Algorithm specific key operations: FrodoKEM
1265
*/
1266

1267
int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* frodo_mode) {
13✔
1268
#if defined(BOTAN_HAS_FRODOKEM)
1269
   if(key == nullptr || privkey == nullptr || frodo_mode == nullptr) {
13✔
1270
      return BOTAN_FFI_ERROR_NULL_POINTER;
1271
   }
1272

1273
   *key = nullptr;
13✔
1274

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

1286
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode) {
13✔
1287
#if defined(BOTAN_HAS_FRODOKEM)
1288
   if(key == nullptr || pubkey == nullptr || frodo_mode == nullptr) {
13✔
1289
      return BOTAN_FFI_ERROR_NULL_POINTER;
1290
   }
1291

1292
   *key = nullptr;
13✔
1293

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

1305
/*
1306
* Algorithm specific key operations : Classic McEliece
1307
*/
1308

1309
int botan_privkey_load_classic_mceliece(botan_privkey_t* key,
17✔
1310
                                        const uint8_t privkey[],
1311
                                        size_t key_len,
1312
                                        const char* cmce_mode) {
1313
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1314
   if(key == nullptr || privkey == nullptr || cmce_mode == nullptr) {
17✔
1315
      return BOTAN_FFI_ERROR_NULL_POINTER;
1316
   }
1317

1318
   *key = nullptr;
17✔
1319

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

1331
int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
17✔
1332
                                       const uint8_t pubkey[],
1333
                                       size_t key_len,
1334
                                       const char* cmce_mode) {
1335
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1336
   if(key == nullptr || pubkey == nullptr || cmce_mode == nullptr) {
17✔
1337
      return BOTAN_FFI_ERROR_NULL_POINTER;
1338
   }
1339

1340
   *key = nullptr;
17✔
1341

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

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

1369
// NOLINTEND(misc-misplaced-const)
1370

1371
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1372
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1373
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1374
}
1✔
1375

1376
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1377
                         const char* aead,
1378
                         const uint8_t ct[],
1379
                         size_t ct_len,
1380
                         const uint8_t ad[],
1381
                         size_t ad_len,
1382
                         uint8_t out[],
1383
                         size_t* out_len) {
1384
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1385
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1386
}
1387

1388
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1389
                         botan_rng_t rng_obj,
1390
                         const char* aead,
1391
                         const uint8_t pt[],
1392
                         size_t pt_len,
1393
                         const uint8_t ad[],
1394
                         size_t ad_len,
1395
                         uint8_t out[],
1396
                         size_t* out_len) {
1397
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1398
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1399
}
1400
}
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