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

randombit / botan / 13481916413

23 Feb 2025 08:06AM UTC coverage: 91.694% (+0.008%) from 91.686%
13481916413

push

github

web-flow
Merge pull request #4704 from randombit/jack/ffi-tidy

FFI cleanups

95826 of 104506 relevant lines covered (91.69%)

11201288.5 hits per line

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

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

9
#include <botan/ffi.h>
10

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

78
#if defined(BOTAN_HAS_ML_KEM)
79
   #include <botan/ml_kem.h>
80
#endif
81

82
#if defined(BOTAN_HAS_FRODOKEM)
83
   #include <botan/frodokem.h>
84
#endif
85

86
#if defined(BOTAN_HAS_ML_DSA)
87
   #include <botan/ml_dsa.h>
88
#endif
89

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

94
#if defined(BOTAN_HAS_CLASSICMCELIECE)
95
   #include <botan/cmce.h>
96
#endif
97

98
namespace {
99

100
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
101

102
// These are always called within an existing try/catch block
103

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

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

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

125
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
126

127
   if(auto pt = Botan::EC_AffinePoint::from_bigint_xy(group, public_x, public_y)) {
6✔
128
      key.reset(new ECPublicKey_t(group, pt.value()));
6✔
129
      return BOTAN_FFI_SUCCESS;
6✔
130
   } else {
131
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
132
   }
133
}
6✔
134

135
#endif
136

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

149
   try {
26✔
150
      return key.get_int_field(field);
26✔
151
   } catch(Botan::Unknown_PK_Field_Name&) {
2✔
152
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
2✔
153
   }
2✔
154
}
155

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

168
   try {
29✔
169
      return key.get_int_field(field);
29✔
170
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
171
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
172
   }
4✔
173
}
174

175
}  // namespace
176

177
extern "C" {
178

179
using namespace Botan_FFI;
180

181
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
182
   if(field_name_cstr == nullptr) {
40✔
183
      return BOTAN_FFI_ERROR_NULL_POINTER;
184
   }
185

186
   const std::string field_name(field_name_cstr);
40✔
187

188
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
189
}
40✔
190

191
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
192
   if(field_name_cstr == nullptr) {
35✔
193
      return BOTAN_FFI_ERROR_NULL_POINTER;
194
   }
195

196
   const std::string field_name(field_name_cstr);
35✔
197

198
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
136✔
199
}
35✔
200

201
/* RSA specific operations */
202

203
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
1✔
204
   if(n_bits < 1024 || n_bits > 16 * 1024) {
1✔
205
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
206
   }
207

208
   std::string n_str = std::to_string(n_bits);
1✔
209

210
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
211
}
1✔
212

213
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✔
214
#if defined(BOTAN_HAS_RSA)
215
   if(key == nullptr) {
2✔
216
      return BOTAN_FFI_ERROR_NULL_POINTER;
217
   }
218
   *key = nullptr;
2✔
219

220
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
221
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
2✔
222
      *key = new botan_privkey_struct(std::move(rsa));
2✔
223
      return BOTAN_FFI_SUCCESS;
2✔
224
   });
2✔
225
#else
226
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
227
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
228
#endif
229
}
230

231
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
232
#if defined(BOTAN_HAS_RSA)
233
   if(key == nullptr || bits == nullptr) {
1✔
234
      return BOTAN_FFI_ERROR_NULL_POINTER;
235
   }
236
   *key = nullptr;
1✔
237

238
   Botan::secure_vector<uint8_t> src(bits, bits + len);
1✔
239
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
240
      Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
1✔
241
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
1✔
242
      *key = new botan_privkey_struct(std::move(rsa));
1✔
243
      return BOTAN_FFI_SUCCESS;
1✔
244
   });
1✔
245
#else
246
   BOTAN_UNUSED(key, bits, len);
247
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
248
#endif
249
}
1✔
250

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

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

272
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) {
1✔
273
   return botan_privkey_get_field(q, key, "q");
1✔
274
}
275

276
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) {
1✔
277
   return botan_privkey_get_field(n, key, "n");
1✔
278
}
279

280
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
281
   return botan_privkey_get_field(e, key, "e");
1✔
282
}
283

284
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
1✔
285
   return botan_privkey_get_field(d, key, "d");
1✔
286
}
287

288
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
289
   return botan_pubkey_get_field(e, key, "e");
1✔
290
}
291

292
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
293
   return botan_pubkey_get_field(n, key, "n");
1✔
294
}
295

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

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

321
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
322
      return BOTAN_FFI_ERROR_NULL_POINTER;
323
   }
324

325
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
326
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
327
   }
328

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

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

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

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

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

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

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

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

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

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

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

404
/* ECDSA specific operations */
405

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

535
/* Diffie Hellman specific operations */
536

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

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

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

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

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

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

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

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

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

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

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

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

642
/* SM2 specific operations */
643

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

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

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

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

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

666
      const std::vector<uint8_t> za =
2✔
667
         Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), ec_key->_public_ec_point());
2✔
668

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

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

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

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

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

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

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

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

733
/* Ed25519 specific operations */
734

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

753
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
754
#if defined(BOTAN_HAS_ED25519)
755
   if(key == nullptr) {
1✔
756
      return BOTAN_FFI_ERROR_NULL_POINTER;
757
   }
758
   *key = nullptr;
1✔
759
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
760
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
761
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
762
      *key = new botan_pubkey_struct(std::move(ed25519));
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_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
772
#if defined(BOTAN_HAS_ED25519)
773
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
774
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
775
         const auto ed_key = ed->raw_private_key_bits();
776
         if(ed_key.size() != 64) {
777
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
778
         }
779
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
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_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
792
#if defined(BOTAN_HAS_ED25519)
793
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
794
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
795
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
796
         if(ed_key.size() != 32) {
797
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
798
         }
799
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
800
         return BOTAN_FFI_SUCCESS;
801
      } else {
802
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
803
      }
804
   });
805
#else
806
   BOTAN_UNUSED(key, output);
807
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
808
#endif
809
}
810

811
/* Ed448 specific operations */
812

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

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

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

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

881
/* X25519 specific operations */
882

883
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
884
#if defined(BOTAN_HAS_X25519)
885
   if(key == nullptr) {
1✔
886
      return BOTAN_FFI_ERROR_NULL_POINTER;
887
   }
888
   *key = nullptr;
1✔
889
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
890
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
891
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
1✔
892
      *key = new botan_privkey_struct(std::move(x25519));
2✔
893
      return BOTAN_FFI_SUCCESS;
2✔
894
   });
2✔
895
#else
896
   BOTAN_UNUSED(key, privkey);
897
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
898
#endif
899
}
900

901
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
902
#if defined(BOTAN_HAS_X25519)
903
   if(key == nullptr) {
1✔
904
      return BOTAN_FFI_ERROR_NULL_POINTER;
905
   }
906
   *key = nullptr;
1✔
907
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
908
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
909
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(pubkey_vec);
1✔
910
      *key = new botan_pubkey_struct(std::move(x25519));
2✔
911
      return BOTAN_FFI_SUCCESS;
1✔
912
   });
2✔
913
#else
914
   BOTAN_UNUSED(key, pubkey);
915
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
916
#endif
917
}
918

919
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
920
#if defined(BOTAN_HAS_X25519)
921
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
922
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
923
         const auto x25519_key = x25519->raw_private_key_bits();
924
         if(x25519_key.size() != 32) {
925
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
926
         }
927
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
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
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
940
#if defined(BOTAN_HAS_X25519)
941
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
942
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
943
         const std::vector<uint8_t>& x25519_key = x25519->public_value();
944
         if(x25519_key.size() != 32) {
945
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
946
         }
947
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
948
         return BOTAN_FFI_SUCCESS;
949
      } else {
950
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
951
      }
952
   });
953
#else
954
   BOTAN_UNUSED(key, output);
955
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
956
#endif
957
}
958

959
/* X448 specific operations */
960

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

978
int botan_pubkey_load_x448(botan_pubkey_t* key, const uint8_t pubkey[56]) {
1✔
979
#if defined(BOTAN_HAS_X448)
980
   if(key == nullptr) {
1✔
981
      return BOTAN_FFI_ERROR_NULL_POINTER;
982
   }
983
   *key = nullptr;
1✔
984
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
985
      auto x448 = std::make_unique<Botan::X448_PublicKey>(std::span(pubkey, 56));
1✔
986
      *key = new botan_pubkey_struct(std::move(x448));
2✔
987
      return BOTAN_FFI_SUCCESS;
1✔
988
   });
1✔
989
#else
990
   BOTAN_UNUSED(key, pubkey);
991
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
992
#endif
993
}
994

995
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56]) {
1✔
996
#if defined(BOTAN_HAS_X448)
997
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
998
      if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
999
         const auto x448_key = x448->raw_private_key_bits();
1000
         Botan::copy_mem(std::span(output, 56), x448_key);
1001
         return BOTAN_FFI_SUCCESS;
1002
      } else {
1003
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1004
      }
1005
   });
1006
#else
1007
   BOTAN_UNUSED(key, output);
1008
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1009
#endif
1010
}
1011

1012
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
2✔
1013
#if defined(BOTAN_HAS_X448)
1014
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
1015
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
1016
         const std::vector<uint8_t>& x448_key = x448->public_value();
1017
         Botan::copy_mem(std::span(output, 56), x448_key);
1018
         return BOTAN_FFI_SUCCESS;
1019
      } else {
1020
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1021
      }
1022
   });
1023
#else
1024
   BOTAN_UNUSED(key, output);
1025
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1026
#endif
1027
}
1028

1029
/*
1030
* Algorithm specific key operations: Kyber
1031
*/
1032

1033
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
1034
#if defined(BOTAN_HAS_KYBER)
1035
   if(key == nullptr) {
4✔
1036
      return BOTAN_FFI_ERROR_NULL_POINTER;
1037
   }
1038
   *key = nullptr;
4✔
1039

1040
   const auto mode = [](size_t len) -> std::optional<Botan::KyberMode> {
12✔
1041
      if(len == 1632) {
4✔
1042
         return Botan::KyberMode::Kyber512_R3;
1✔
1043
      } else if(len == 2400) {
3✔
1044
         return Botan::KyberMode::Kyber768_R3;
2✔
1045
      } else if(len == 3168) {
1✔
1046
         return Botan::KyberMode::Kyber1024_R3;
1✔
1047
      } else {
1048
         return {};
×
1049
      }
1050
   }(key_len);
4✔
1051

1052
   if(mode.has_value()) {
4✔
1053
      return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1054
         auto kyber = std::make_unique<Botan::Kyber_PrivateKey>(std::span{privkey, key_len}, *mode);
4✔
1055
         *key = new botan_privkey_struct(std::move(kyber));
4✔
1056
         return BOTAN_FFI_SUCCESS;
4✔
1057
      });
4✔
1058
   } else {
1059
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
1060
   }
1061
#else
1062
   BOTAN_UNUSED(key, key_len, privkey);
1063
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1064
#endif
1065
}
1066

1067
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
1068
#if defined(BOTAN_HAS_KYBER)
1069
   if(key == nullptr) {
4✔
1070
      return BOTAN_FFI_ERROR_NULL_POINTER;
1071
   }
1072
   *key = nullptr;
4✔
1073

1074
   const auto mode = [](size_t len) -> std::optional<Botan::KyberMode> {
12✔
1075
      if(len == 800) {
4✔
1076
         return Botan::KyberMode::Kyber512_R3;
1✔
1077
      } else if(len == 1184) {
3✔
1078
         return Botan::KyberMode::Kyber768_R3;
2✔
1079
      } else if(len == 1568) {
1✔
1080
         return Botan::KyberMode::Kyber1024_R3;
1✔
1081
      } else {
1082
         return {};
×
1083
      }
1084
   }(key_len);
4✔
1085

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

1099
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1100
#if defined(BOTAN_HAS_KYBER)
1101
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
16✔
1102
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1103
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1104
      } else {
1105
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1106
      }
1107
   });
1108
#else
1109
   BOTAN_UNUSED(key, ctx, view);
1110
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1111
#endif
1112
}
1113

1114
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1115
#if defined(BOTAN_HAS_KYBER)
1116
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
32✔
1117
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1118
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1119
      } else {
1120
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1121
      }
1122
   });
1123
#else
1124
   BOTAN_UNUSED(key, ctx, view);
1125
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1126
#endif
1127
}
1128

1129
/*
1130
* Algorithm specific key operations: ML-KEM
1131
*/
1132

1133
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1134
#if defined(BOTAN_HAS_ML_KEM)
1135
   if(key == nullptr || privkey == nullptr || mlkem_mode == nullptr) {
4✔
1136
      return BOTAN_FFI_ERROR_NULL_POINTER;
1137
   }
1138

1139
   *key = nullptr;
4✔
1140

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

1147
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1148
      *key = new botan_privkey_struct(std::move(mlkem_key));
4✔
1149
      return BOTAN_FFI_SUCCESS;
4✔
1150
   });
4✔
1151
#else
1152
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1153
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1154
#endif
1155
}
1156

1157
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
4✔
1158
#if defined(BOTAN_HAS_ML_KEM)
1159
   if(key == nullptr || pubkey == nullptr || mlkem_mode == nullptr) {
4✔
1160
      return BOTAN_FFI_ERROR_NULL_POINTER;
1161
   }
1162

1163
   *key = nullptr;
4✔
1164

1165
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1166
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1167
      if(!mode.is_ml_kem()) {
4✔
1168
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1169
      }
1170

1171
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PublicKey>(std::span{pubkey, key_len}, mode.mode());
4✔
1172
      *key = new botan_pubkey_struct(std::move(mlkem_key));
8✔
1173
      return BOTAN_FFI_SUCCESS;
4✔
1174
   });
4✔
1175
#else
1176
   BOTAN_UNUSED(key, key_len, pubkey, mlkem_mode);
1177
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1178
#endif
1179
}
1180

1181
/*
1182
* Algorithm specific key operations: ML-DSA
1183
*/
1184

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

1191
   *key = nullptr;
4✔
1192

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

1199
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1200
      *key = new botan_privkey_struct(std::move(mldsa_key));
4✔
1201
      return BOTAN_FFI_SUCCESS;
4✔
1202
   });
4✔
1203
#else
1204
   BOTAN_UNUSED(key, key_len, privkey, mldsa_mode);
1205
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1206
#endif
1207
}
1208

1209
int botan_pubkey_load_ml_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mldsa_mode) {
4✔
1210
#if defined(BOTAN_HAS_ML_DSA)
1211
   if(key == nullptr || pubkey == nullptr || mldsa_mode == nullptr) {
4✔
1212
      return BOTAN_FFI_ERROR_NULL_POINTER;
1213
   }
1214

1215
   *key = nullptr;
4✔
1216

1217
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1218
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1219
      if(!mode.is_ml_dsa()) {
4✔
1220
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1221
      }
1222

1223
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
4✔
1224
      *key = new botan_pubkey_struct(std::move(mldsa_key));
8✔
1225
      return BOTAN_FFI_SUCCESS;
4✔
1226
   });
4✔
1227
#else
1228
   BOTAN_UNUSED(key, key_len, pubkey, mldsa_mode);
1229
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1230
#endif
1231
}
1232

1233
/*
1234
* Algorithm specific key operations: SLH-DSA
1235
*/
1236

1237
int botan_privkey_load_slh_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1238
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1239
   if(key == nullptr || privkey == nullptr || slhdsa_mode == nullptr) {
13✔
1240
      return BOTAN_FFI_ERROR_NULL_POINTER;
1241
   }
1242

1243
   *key = nullptr;
13✔
1244

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

1251
      auto slhdsa_key = std::make_unique<Botan::SLH_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1252
      *key = new botan_privkey_struct(std::move(slhdsa_key));
13✔
1253
      return BOTAN_FFI_SUCCESS;
13✔
1254
   });
13✔
1255
#else
1256
   BOTAN_UNUSED(key, key_len, privkey, slhdsa_mode);
1257
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1258
#endif
1259
}
1260

1261
int botan_pubkey_load_slh_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1262
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1263
   if(key == nullptr || pubkey == nullptr || slhdsa_mode == nullptr) {
13✔
1264
      return BOTAN_FFI_ERROR_NULL_POINTER;
1265
   }
1266

1267
   *key = nullptr;
13✔
1268

1269
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1270
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1271
      if(!mode.is_slh_dsa()) {
13✔
1272
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1273
      }
1274

1275
      auto mldsa_key = std::make_unique<Botan::SLH_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1276
      *key = new botan_pubkey_struct(std::move(mldsa_key));
26✔
1277
      return BOTAN_FFI_SUCCESS;
13✔
1278
   });
13✔
1279
#else
1280
   BOTAN_UNUSED(key, key_len, pubkey, slhdsa_mode);
1281
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1282
#endif
1283
}
1284

1285
/*
1286
* Algorithm specific key operations: FrodoKEM
1287
*/
1288

1289
int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* frodo_mode) {
13✔
1290
#if defined(BOTAN_HAS_FRODOKEM)
1291
   if(key == nullptr || privkey == nullptr || frodo_mode == nullptr) {
13✔
1292
      return BOTAN_FFI_ERROR_NULL_POINTER;
1293
   }
1294

1295
   *key = nullptr;
13✔
1296

1297
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1298
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1299
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1300
      *key = new botan_privkey_struct(std::move(frodo_key));
13✔
1301
      return BOTAN_FFI_SUCCESS;
13✔
1302
   });
13✔
1303
#else
1304
   BOTAN_UNUSED(key, privkey, key_len, frodo_mode);
1305
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1306
#endif
1307
}
1308

1309
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode) {
13✔
1310
#if defined(BOTAN_HAS_FRODOKEM)
1311
   if(key == nullptr || pubkey == nullptr || frodo_mode == nullptr) {
13✔
1312
      return BOTAN_FFI_ERROR_NULL_POINTER;
1313
   }
1314

1315
   *key = nullptr;
13✔
1316

1317
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1318
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1319
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1320
      *key = new botan_pubkey_struct(std::move(frodo_key));
26✔
1321
      return BOTAN_FFI_SUCCESS;
13✔
1322
   });
13✔
1323
#else
1324
   BOTAN_UNUSED(key, pubkey, key_len, frodo_mode);
1325
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1326
#endif
1327
}
1328

1329
/*
1330
* Algorithm specific key operations : Classic McEliece
1331
*/
1332

1333
int botan_privkey_load_classic_mceliece(botan_privkey_t* key,
17✔
1334
                                        const uint8_t privkey[],
1335
                                        size_t key_len,
1336
                                        const char* cmce_mode) {
1337
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1338
   if(key == nullptr || privkey == nullptr || cmce_mode == nullptr) {
17✔
1339
      return BOTAN_FFI_ERROR_NULL_POINTER;
1340
   }
1341

1342
   *key = nullptr;
17✔
1343

1344
   return ffi_guard_thunk(__func__, [=]() -> int {
34✔
1345
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1346
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PrivateKey>(std::span{privkey, key_len}, mode);
17✔
1347
      *key = new botan_privkey_struct(std::move(cmce_key));
17✔
1348
      return BOTAN_FFI_SUCCESS;
17✔
1349
   });
17✔
1350
#else
1351
   BOTAN_UNUSED(key, privkey, key_len, cmce_mode);
1352
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1353
#endif
1354
}
1355

1356
int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
17✔
1357
                                       const uint8_t pubkey[],
1358
                                       size_t key_len,
1359
                                       const char* cmce_mode) {
1360
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1361
   if(key == nullptr || pubkey == nullptr || cmce_mode == nullptr) {
17✔
1362
      return BOTAN_FFI_ERROR_NULL_POINTER;
1363
   }
1364

1365
   *key = nullptr;
17✔
1366

1367
   return ffi_guard_thunk(__func__, [=]() -> int {
34✔
1368
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1369
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PublicKey>(std::span{pubkey, key_len}, mode);
17✔
1370
      *key = new botan_pubkey_struct(std::move(cmce_key));
34✔
1371
      return BOTAN_FFI_SUCCESS;
17✔
1372
   });
17✔
1373
#else
1374
   BOTAN_UNUSED(key, pubkey, key_len, cmce_mode);
1375
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1376
#endif
1377
}
1378

1379
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1380
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1381
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1382
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1383
         auto pt = ecc->_public_ec_point().serialize_uncompressed();
1384
         return invoke_view_callback(view, ctx, pt);
1385
      } else {
1386
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1387
      }
1388
   });
1389
#else
1390
   BOTAN_UNUSED(key, view, ctx);
1391
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1392
#endif
1393
}
1394

1395
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1396
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1397
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1398
}
1✔
1399

1400
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1401
                         const char* aead,
1402
                         const uint8_t ct[],
1403
                         size_t ct_len,
1404
                         const uint8_t ad[],
1405
                         size_t ad_len,
1406
                         uint8_t out[],
1407
                         size_t* out_len) {
1408
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1409
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1410
}
1411

1412
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1413
                         botan_rng_t rng_obj,
1414
                         const char* aead,
1415
                         const uint8_t pt[],
1416
                         size_t pt_len,
1417
                         const uint8_t ad[],
1418
                         size_t ad_len,
1419
                         uint8_t out[],
1420
                         size_t* out_len) {
1421
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1422
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1423
}
1424
}
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