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

randombit / botan / 11364833501

16 Oct 2024 11:36AM UTC coverage: 91.11% (-0.002%) from 91.112%
11364833501

push

github

web-flow
Merge pull request #4374 from Rohde-Schwarz/pqc/ml_kem_compat

ML-KEM: Provide type aliases

90987 of 99865 relevant lines covered (91.11%)

9384224.82 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_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/dilithium.h>
88
#endif
89

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

94
namespace {
95

96
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
97

98
// These are always called within an existing try/catch block
99

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

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

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

121
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
122

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

131
#endif
132

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

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

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

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

171
}  // namespace
172

173
extern "C" {
174

175
using namespace Botan_FFI;
176

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

182
   const std::string field_name(field_name_cstr);
40✔
183

184
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
185
}
40✔
186

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

192
   const std::string field_name(field_name_cstr);
35✔
193

194
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
140✔
195
}
35✔
196

197
/* RSA specific operations */
198

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

204
   std::string n_str = std::to_string(n_bits);
1✔
205

206
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
207
}
1✔
208

209
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✔
210
#if defined(BOTAN_HAS_RSA)
211
   *key = nullptr;
2✔
212

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

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

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

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

255
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) {
1✔
256
   return botan_privkey_get_field(p, key, "p");
1✔
257
}
258

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

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

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

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

275
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
276
   return botan_pubkey_get_field(e, key, "e");
1✔
277
}
278

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

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

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

307
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
308
      return BOTAN_FFI_ERROR_NULL_POINTER;
309
   }
310

311
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
312
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
313
   }
314

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

328
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✔
329
#if defined(BOTAN_HAS_DSA)
330
   *key = nullptr;
2✔
331

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

344
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✔
345
#if defined(BOTAN_HAS_DSA)
346
   *key = nullptr;
2✔
347

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

360
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
361
   return botan_privkey_get_field(x, key, "x");
2✔
362
}
363

364
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
2✔
365
   return botan_pubkey_get_field(p, key, "p");
2✔
366
}
367

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

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

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

380
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
381
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
382
}
383

384
/* ECDSA specific operations */
385

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

392
      if(ec_key == nullptr) {
1✔
393
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
394
      }
395

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

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

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

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

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

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

445
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
446
      return BOTAN_FFI_ERROR_NULL_POINTER;
447
   }
448

449
   if((pbits < 1024) || (qbits < 160)) {
1✔
450
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
451
   }
452

453
   Botan::DL_Group::PrimeType prime_type =
1✔
454
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
455

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

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

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

499
/* Diffie Hellman specific operations */
500

501
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
502
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
503
}
504

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

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

535
/* ECDH + x25519/x448 specific operations */
536

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

542
   const std::string params(param_str);
2✔
543

544
   if(params == "x25519" || params == "curve25519") {
2✔
545
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
546
   }
547

548
   if(params == "x448") {
2✔
549
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
550
   }
551

552
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
553
}
2✔
554

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

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

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

591
/* SM2 specific operations */
592

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

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

607
      if(ec_key == nullptr) {
2✔
608
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
609
      }
610

611
      if(ec_key->algo_name() != "SM2") {
2✔
612
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
613
      }
614

615
      const std::string ident_str(ident);
2✔
616
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
617

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

620
      return write_vec_output(out, out_len, za);
2✔
621
   });
4✔
622
#else
623
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
624
#endif
625
}
626

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

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

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

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

670
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
671
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
672
}
673

674
/* Ed25519 specific operations */
675

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

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

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

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

744
/* Ed448 specific operations */
745

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

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

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

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

808
/* X25519 specific operations */
809

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

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

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

859
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
860
#if defined(BOTAN_HAS_X25519)
861
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
862
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
863
         const std::vector<uint8_t>& x25519_key = x25519->public_value();
864
         if(x25519_key.size() != 32)
865
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
866
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
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
/* X448 specific operations */
879

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

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

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

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

942
/*
943
* Algorithm specific key operations: Kyber
944
*/
945

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

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

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

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

1046
/*
1047
* Algorithm specific key operations: ML-KEM
1048
*/
1049

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

1056
   *key = nullptr;
4✔
1057

1058
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1059
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1060
      if(!mode.is_ml_kem()) {
4✔
1061
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1062
      }
1063

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

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

1080
   *key = nullptr;
4✔
1081

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

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

1098
/*
1099
* Algorithm specific key operations: ML-DSA
1100
*/
1101

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

1108
   *key = nullptr;
4✔
1109

1110
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1111
      auto mode = Botan::DilithiumMode(mldsa_mode);
4✔
1112
      if(!mode.is_ml_dsa()) {
4✔
1113
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1114
      }
1115

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

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

1132
   *key = nullptr;
4✔
1133

1134
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1135
      auto mode = Botan::DilithiumMode(mldsa_mode);
4✔
1136
      if(!mode.is_ml_dsa()) {
4✔
1137
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1138
      }
1139

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

1150
/*
1151
* Algorithm specific key operations: SLH-DSA
1152
*/
1153

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

1160
   *key = nullptr;
13✔
1161

1162
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1163
      auto mode = Botan::Sphincs_Parameters::create(slhdsa_mode);
13✔
1164
      if(!mode.is_slh_dsa()) {
13✔
1165
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1166
      }
1167

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

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

1184
   *key = nullptr;
13✔
1185

1186
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1187
      auto mode = Botan::Sphincs_Parameters::create(slhdsa_mode);
13✔
1188
      if(!mode.is_slh_dsa()) {
13✔
1189
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1190
      }
1191

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

1202
/*
1203
* Algorithm specific key operations: FrodoKEM
1204
*/
1205

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

1212
   *key = nullptr;
13✔
1213

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

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

1232
   *key = nullptr;
13✔
1233

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

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

1262
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1263
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1264
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1265
}
1✔
1266

1267
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1268
                         const char* aead,
1269
                         const uint8_t ct[],
1270
                         size_t ct_len,
1271
                         const uint8_t ad[],
1272
                         size_t ad_len,
1273
                         uint8_t out[],
1274
                         size_t* out_len) {
1275
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1276
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1277
}
1278

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