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

randombit / botan / 11346962432

15 Oct 2024 01:20PM UTC coverage: 91.112% (-0.4%) from 91.512%
11346962432

push

github

web-flow
Merge pull request #4291 from Rohde-Schwarz/feature/slh-dsa

PQC: SLH-DSA

90987 of 99863 relevant lines covered (91.11%)

9307997.46 hits per line

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

98.31
/src/lib/ffi/ffi_pkey_algs.cpp
1
/*
2
* (C) 2015,2017 Jack Lloyd
3
* (C) 2017 Ribose Inc
4
* (C) 2018 René Korthaus, Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include <botan/ffi.h>
10

11
#include <botan/hash.h>
12
#include <botan/pem.h>
13
#include <botan/internal/ffi_mp.h>
14
#include <botan/internal/ffi_pkey.h>
15
#include <botan/internal/ffi_rng.h>
16
#include <botan/internal/ffi_util.h>
17

18
#if defined(BOTAN_HAS_DL_GROUP)
19
   #include <botan/dl_group.h>
20
#endif
21

22
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
23
   #include <botan/ecc_key.h>
24
#endif
25

26
#if defined(BOTAN_HAS_RSA)
27
   #include <botan/rsa.h>
28
#endif
29

30
#if defined(BOTAN_HAS_ELGAMAL)
31
   #include <botan/elgamal.h>
32
#endif
33

34
#if defined(BOTAN_HAS_DSA)
35
   #include <botan/dsa.h>
36
#endif
37

38
#if defined(BOTAN_HAS_ECDSA)
39
   #include <botan/ecdsa.h>
40
#endif
41

42
#if defined(BOTAN_HAS_SM2)
43
   #include <botan/sm2.h>
44
#endif
45

46
#if defined(BOTAN_HAS_ECDH)
47
   #include <botan/ecdh.h>
48
#endif
49

50
#if defined(BOTAN_HAS_X25519)
51
   #include <botan/x25519.h>
52
#endif
53

54
#if defined(BOTAN_HAS_X448)
55
   #include <botan/x448.h>
56
#endif
57

58
#if defined(BOTAN_HAS_ED25519)
59
   #include <botan/ed25519.h>
60
#endif
61

62
#if defined(BOTAN_HAS_ED448)
63
   #include <botan/ed448.h>
64
#endif
65

66
#if defined(BOTAN_HAS_MCELIECE)
67
   #include <botan/mceliece.h>
68
#endif
69

70
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
71
   #include <botan/dh.h>
72
#endif
73

74
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_ML_KEM)
75
   #include <botan/kyber.h>
76
   #include <botan/internal/kyber_constants.h>
77
#endif
78

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

83
#if defined(BOTAN_HAS_ML_DSA)
84
   #include <botan/dilithium.h>
85
#endif
86

87
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
88
   #include <botan/sphincsplus.h>
89
#endif
90

91
namespace {
92

93
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
94

95
// These are always called within an existing try/catch block
96

97
template <class ECPrivateKey_t>
98
int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& scalar, const char* curve_name) {
9✔
99
   if(curve_name == nullptr) {
9✔
100
      return BOTAN_FFI_ERROR_NULL_POINTER;
101
   }
102

103
   Botan::Null_RNG null_rng;
9✔
104
   const auto grp = Botan::EC_Group::from_name(curve_name);
9✔
105
   key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
9✔
106
   return BOTAN_FFI_SUCCESS;
107
}
9✔
108

109
template <class ECPublicKey_t>
110
int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
6✔
111
                   const Botan::BigInt& public_x,
112
                   const Botan::BigInt& public_y,
113
                   const char* curve_name) {
114
   if(curve_name == nullptr) {
6✔
115
      return BOTAN_FFI_ERROR_NULL_POINTER;
116
   }
117

118
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
119

120
   if(auto pt = Botan::EC_AffinePoint::from_bigint_xy(group, public_x, public_y)) {
6✔
121
      key.reset(new ECPublicKey_t(group, pt->to_legacy_point()));
6✔
122
      return BOTAN_FFI_SUCCESS;
6✔
123
   } else {
124
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
125
   }
126
}
6✔
127

128
#endif
129

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

142
   try {
26✔
143
      return key.get_int_field(field);
26✔
144
   } catch(Botan::Unknown_PK_Field_Name&) {
2✔
145
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
2✔
146
   }
2✔
147
}
148

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

161
   try {
29✔
162
      return key.get_int_field(field);
29✔
163
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
164
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
165
   }
4✔
166
}
167

168
}  // namespace
169

170
extern "C" {
171

172
using namespace Botan_FFI;
173

174
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
175
   if(field_name_cstr == nullptr) {
40✔
176
      return BOTAN_FFI_ERROR_NULL_POINTER;
177
   }
178

179
   const std::string field_name(field_name_cstr);
40✔
180

181
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
182
}
40✔
183

184
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
185
   if(field_name_cstr == nullptr) {
35✔
186
      return BOTAN_FFI_ERROR_NULL_POINTER;
187
   }
188

189
   const std::string field_name(field_name_cstr);
35✔
190

191
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
140✔
192
}
35✔
193

194
/* RSA specific operations */
195

196
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
1✔
197
   if(n_bits < 1024 || n_bits > 16 * 1024) {
1✔
198
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
199
   }
200

201
   std::string n_str = std::to_string(n_bits);
1✔
202

203
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
204
}
1✔
205

206
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✔
207
#if defined(BOTAN_HAS_RSA)
208
   *key = nullptr;
2✔
209

210
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
211
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
2✔
212
      *key = new botan_privkey_struct(std::move(rsa));
2✔
213
      return BOTAN_FFI_SUCCESS;
2✔
214
   });
4✔
215
#else
216
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
217
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
218
#endif
219
}
220

221
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
222
#if defined(BOTAN_HAS_RSA)
223
   *key = nullptr;
1✔
224

225
   Botan::secure_vector<uint8_t> src(bits, bits + len);
1✔
226
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
227
      Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
1✔
228
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
1✔
229
      *key = new botan_privkey_struct(std::move(rsa));
1✔
230
      return BOTAN_FFI_SUCCESS;
1✔
231
   });
1✔
232
#else
233
   BOTAN_UNUSED(key, bits, len);
234
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
235
#endif
236
}
1✔
237

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

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

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

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

264
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
265
   return botan_privkey_get_field(e, key, "e");
1✔
266
}
267

268
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
1✔
269
   return botan_privkey_get_field(d, key, "d");
1✔
270
}
271

272
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
273
   return botan_pubkey_get_field(e, key, "e");
1✔
274
}
275

276
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
277
   return botan_pubkey_get_field(n, key, "n");
1✔
278
}
279

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

300
/* DSA specific operations */
301
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
302
#if defined(BOTAN_HAS_DSA)
303

304
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
305
      return BOTAN_FFI_ERROR_NULL_POINTER;
306
   }
307

308
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
309
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
310
   }
311

312
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
313
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
314
      Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
1✔
315
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
1✔
316
      *key = new botan_privkey_struct(std::move(dsa));
2✔
317
      return BOTAN_FFI_SUCCESS;
2✔
318
   });
2✔
319
#else
320
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
321
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
322
#endif
323
}
324

325
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✔
326
#if defined(BOTAN_HAS_DSA)
327
   *key = nullptr;
2✔
328

329
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
330
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
331
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
2✔
332
      *key = new botan_privkey_struct(std::move(dsa));
4✔
333
      return BOTAN_FFI_SUCCESS;
4✔
334
   });
6✔
335
#else
336
   BOTAN_UNUSED(key, p, q, g, x);
337
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
338
#endif
339
}
340

341
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✔
342
#if defined(BOTAN_HAS_DSA)
343
   *key = nullptr;
2✔
344

345
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
346
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
347
      auto dsa = std::make_unique<Botan::DSA_PublicKey>(group, safe_get(y));
2✔
348
      *key = new botan_pubkey_struct(std::move(dsa));
4✔
349
      return BOTAN_FFI_SUCCESS;
2✔
350
   });
6✔
351
#else
352
   BOTAN_UNUSED(key, p, q, g, y);
353
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
354
#endif
355
}
356

357
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
358
   return botan_privkey_get_field(x, key, "x");
2✔
359
}
360

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

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

369
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
370
   return botan_pubkey_get_field(g, key, "g");
2✔
371
}
372

373
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
374
   return botan_pubkey_get_field(y, key, "y");
2✔
375
}
376

377
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
378
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
379
}
380

381
/* ECDSA specific operations */
382

383
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key) {
1✔
384
#if defined(BOTAN_HAS_ECC_KEY)
385
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
386
      const Botan::Public_Key& pub_key = safe_get(key);
1✔
387
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
1✔
388

389
      if(ec_key == nullptr) {
1✔
390
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
391
      }
392

393
      return ec_key->domain().used_explicit_encoding() ? 1 : 0;
1✔
394
   });
1✔
395
#else
396
   BOTAN_UNUSED(key);
397
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
398
#endif
399
}
400

401
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
402
                            const botan_mp_t public_x,
403
                            const botan_mp_t public_y,
404
                            const char* curve_name) {
405
#if defined(BOTAN_HAS_ECDSA)
406
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
407
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
408

409
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
410
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
411
         *key = new botan_pubkey_struct(std::move(p_key));
4✔
412
      }
413

414
      return rc;
2✔
415
   });
4✔
416
#else
417
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
418
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
419
#endif
420
}
421

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

438
/* ElGamal specific operations */
439
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
440
#if defined(BOTAN_HAS_ELGAMAL)
441

442
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
443
      return BOTAN_FFI_ERROR_NULL_POINTER;
444
   }
445

446
   if((pbits < 1024) || (qbits < 160)) {
1✔
447
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
448
   }
449

450
   Botan::DL_Group::PrimeType prime_type =
1✔
451
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
452

453
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
454
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
455
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
456
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
457
      *key = new botan_privkey_struct(std::move(elg));
2✔
458
      return BOTAN_FFI_SUCCESS;
2✔
459
   });
2✔
460
#else
461
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
462
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
463
#endif
464
}
465

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

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

496
/* Diffie Hellman specific operations */
497

498
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
499
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
500
}
501

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

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

532
/* ECDH + x25519/x448 specific operations */
533

534
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
535
   if(param_str == nullptr) {
2✔
536
      return BOTAN_FFI_ERROR_NULL_POINTER;
537
   }
538

539
   const std::string params(param_str);
2✔
540

541
   if(params == "x25519" || params == "curve25519") {
2✔
542
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
543
   }
544

545
   if(params == "x448") {
2✔
546
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
547
   }
548

549
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
550
}
2✔
551

552
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
553
                           const botan_mp_t public_x,
554
                           const botan_mp_t public_y,
555
                           const char* curve_name) {
556
#if defined(BOTAN_HAS_ECDH)
557
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
558
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
559
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
560

561
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
562
         *key = new botan_pubkey_struct(std::move(p_key));
2✔
563
      }
564
      return rc;
1✔
565
   });
2✔
566
#else
567
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
568
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
569
#endif
570
}
571

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

588
/* SM2 specific operations */
589

590
int botan_pubkey_sm2_compute_za(
2✔
591
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
592
   if(out == nullptr || out_len == nullptr) {
2✔
593
      return BOTAN_FFI_ERROR_NULL_POINTER;
594
   }
595
   if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
596
      return BOTAN_FFI_ERROR_NULL_POINTER;
597
   }
598

599
#if defined(BOTAN_HAS_SM2)
600
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
601
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
602
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
603

604
      if(ec_key == nullptr) {
2✔
605
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
606
      }
607

608
      if(ec_key->algo_name() != "SM2") {
2✔
609
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
610
      }
611

612
      const std::string ident_str(ident);
2✔
613
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
614

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

617
      return write_vec_output(out, out_len, za);
2✔
618
   });
4✔
619
#else
620
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
621
#endif
622
}
623

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

643
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
644
#if defined(BOTAN_HAS_SM2)
645
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
646
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
647
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
648

649
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
650
         *key = new botan_privkey_struct(std::move(p_key));
6✔
651
      }
652
      return rc;
3✔
653
   });
6✔
654
#else
655
   BOTAN_UNUSED(key, scalar, curve_name);
656
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
657
#endif
658
}
659

660
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
661
                              const botan_mp_t public_x,
662
                              const botan_mp_t public_y,
663
                              const char* curve_name) {
664
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
665
}
666

667
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
668
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
669
}
670

671
/* Ed25519 specific operations */
672

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

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

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

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

741
/* Ed448 specific operations */
742

743
int botan_privkey_load_ed448(botan_privkey_t* key, const uint8_t privkey[57]) {
1✔
744
#if defined(BOTAN_HAS_ED448)
745
   *key = nullptr;
1✔
746
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
747
      auto ed448 = std::make_unique<Botan::Ed448_PrivateKey>(std::span(privkey, 57));
1✔
748
      *key = new botan_privkey_struct(std::move(ed448));
2✔
749
      return BOTAN_FFI_SUCCESS;
1✔
750
   });
2✔
751
#else
752
   BOTAN_UNUSED(key, privkey);
753
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
754
#endif
755
}
756

757
int botan_pubkey_load_ed448(botan_pubkey_t* key, const uint8_t pubkey[57]) {
1✔
758
#if defined(BOTAN_HAS_ED448)
759
   *key = nullptr;
1✔
760
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
761
      auto ed448 = std::make_unique<Botan::Ed448_PublicKey>(std::span(pubkey, 57));
1✔
762
      *key = new botan_pubkey_struct(std::move(ed448));
2✔
763
      return BOTAN_FFI_SUCCESS;
1✔
764
   });
2✔
765
#else
766
   BOTAN_UNUSED(key, pubkey);
767
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
768
#endif
769
}
770

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

788
int botan_pubkey_ed448_get_pubkey(botan_pubkey_t key, uint8_t output[57]) {
1✔
789
#if defined(BOTAN_HAS_ED448)
790
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
3✔
791
      if(auto ed = dynamic_cast<const Botan::Ed448_PublicKey*>(&k)) {
792
         const auto ed_key = ed->public_key_bits();
793
         Botan::copy_mem(std::span(output, 57), ed_key);
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
/* X25519 specific operations */
806

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

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

837
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
838
#if defined(BOTAN_HAS_X25519)
839
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
840
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
841
         const auto x25519_key = x25519->raw_private_key_bits();
842
         if(x25519_key.size() != 32)
843
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
844
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
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_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
857
#if defined(BOTAN_HAS_X25519)
858
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
859
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
860
         const std::vector<uint8_t>& x25519_key = x25519->public_value();
861
         if(x25519_key.size() != 32)
862
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
863
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
864
         return BOTAN_FFI_SUCCESS;
865
      } else {
866
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
867
      }
868
   });
869
#else
870
   BOTAN_UNUSED(key, output);
871
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
872
#endif
873
}
874

875
/* X448 specific operations */
876

877
int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
1✔
878
#if defined(BOTAN_HAS_X448)
879
   *key = nullptr;
1✔
880
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
881
      auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span(privkey, 56));
1✔
882
      *key = new botan_privkey_struct(std::move(x448));
2✔
883
      return BOTAN_FFI_SUCCESS;
1✔
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_x448(botan_pubkey_t* key, const uint8_t pubkey[56]) {
1✔
892
#if defined(BOTAN_HAS_X448)
893
   *key = nullptr;
1✔
894
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
895
      auto x448 = std::make_unique<Botan::X448_PublicKey>(std::span(pubkey, 56));
1✔
896
      *key = new botan_pubkey_struct(std::move(x448));
2✔
897
      return BOTAN_FFI_SUCCESS;
1✔
898
   });
2✔
899
#else
900
   BOTAN_UNUSED(key, pubkey);
901
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
902
#endif
903
}
904

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

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

939
/*
940
* Algorithm specific key operations: Kyber
941
*/
942

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

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

1013
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1014
#if defined(BOTAN_HAS_KYBER)
1015
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
12✔
1016
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1017
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1018
      } else {
1019
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1020
      }
1021
   });
1022
#else
1023
   BOTAN_UNUSED(key, ctx, view);
1024
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1025
#endif
1026
}
1027

1028
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1029
#if defined(BOTAN_HAS_KYBER)
1030
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1031
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1032
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1033
      } else {
1034
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1035
      }
1036
   });
1037
#else
1038
   BOTAN_UNUSED(key, ctx, view);
1039
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1040
#endif
1041
}
1042

1043
/*
1044
* Algorithm specific key operations: ML-KEM
1045
*/
1046

1047
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1048
#if defined(BOTAN_HAS_ML_KEM)
1049
   if(key == nullptr || privkey == nullptr || mlkem_mode == nullptr) {
4✔
1050
      return BOTAN_FFI_ERROR_NULL_POINTER;
1051
   }
1052

1053
   *key = nullptr;
4✔
1054

1055
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1056
      auto mode = Botan::KyberConstants(Botan::KyberMode(mlkem_mode));
4✔
1057
      if(!mode.mode().is_ml_kem()) {
4✔
1058
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1059
      }
1060

1061
      if(key_len != mode.private_key_bytes()) {
4✔
1062
         return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
1063
      }
1064

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

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

1081
   *key = nullptr;
4✔
1082

1083
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1084
      auto mode = Botan::KyberConstants(Botan::KyberMode(mlkem_mode));
4✔
1085
      if(!mode.mode().is_ml_kem()) {
4✔
1086
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1087
      }
1088

1089
      if(key_len != mode.public_key_bytes()) {
4✔
1090
         return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
1091
      }
1092

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

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

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

1113
   *key = nullptr;
4✔
1114

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

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

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

1137
   *key = nullptr;
4✔
1138

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

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

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

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

1165
   *key = nullptr;
13✔
1166

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

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

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

1189
   *key = nullptr;
13✔
1190

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

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

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

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

1217
   *key = nullptr;
13✔
1218

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

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

1237
   *key = nullptr;
13✔
1238

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

1251
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1252
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1253
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
1254
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1255
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
1256
         return invoke_view_callback(view, ctx, pt);
1257
      } else {
1258
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1259
      }
1260
   });
1261
#else
1262
   BOTAN_UNUSED(key, view, ctx);
1263
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1264
#endif
1265
}
1266

1267
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1268
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1269
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1270
}
1✔
1271

1272
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1273
                         const char* aead,
1274
                         const uint8_t ct[],
1275
                         size_t ct_len,
1276
                         const uint8_t ad[],
1277
                         size_t ad_len,
1278
                         uint8_t out[],
1279
                         size_t* out_len) {
1280
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1281
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1282
}
1283

1284
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1285
                         botan_rng_t rng_obj,
1286
                         const char* aead,
1287
                         const uint8_t pt[],
1288
                         size_t pt_len,
1289
                         const uint8_t ad[],
1290
                         size_t ad_len,
1291
                         uint8_t out[],
1292
                         size_t* out_len) {
1293
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1294
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1295
}
1296
}
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