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

randombit / botan / 25476046290

07 May 2026 01:38AM UTC coverage: 89.331%. Remained the same
25476046290

push

github

randombit
Update for 3.12.0 release

107574 of 120422 relevant lines covered (89.33%)

11308499.77 hits per line

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

96.72
/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/assert.h>
12
#include <botan/ec_group.h>
13
#include <botan/hash.h>
14
#include <botan/mem_ops.h>
15
#include <botan/pem.h>
16
#include <botan/internal/ffi_ec.h>
17
#include <botan/internal/ffi_mp.h>
18
#include <botan/internal/ffi_pkey.h>
19
#include <botan/internal/ffi_rng.h>
20
#include <botan/internal/ffi_util.h>
21

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

98
namespace {
99

100
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
101

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

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

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

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

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

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

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

142
template <class ECPublicKey_t>
143
int pubkey_load_ec_sec1(std::unique_ptr<ECPublicKey_t>& key,
14✔
144
                        std::span<const uint8_t> sec1,
145
                        std::string_view curve_name) {
146
   if(!Botan::EC_Group::supports_named_group(curve_name)) {
14✔
147
      return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
148
   }
149

150
   const auto group = Botan::EC_Group::from_name(curve_name);
14✔
151

152
   if(auto pt = Botan::EC_AffinePoint::deserialize(group, sec1)) {
14✔
153
      key.reset(new ECPublicKey_t(group, pt.value()));
14✔
154
      return BOTAN_FFI_SUCCESS;
14✔
155
   } else {
156
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
157
   }
158
}
14✔
159

160
#endif
161

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

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

181
Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
35✔
182
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
183
   // Not currently handled by get_int_field
184
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
35✔
185
      if(field == "public_x") {
16✔
186
         return Botan::BigInt::from_bytes(ecc->_public_ec_point().x_bytes());
4✔
187
      } else if(field == "public_y") {
14✔
188
         return Botan::BigInt::from_bytes(ecc->_public_ec_point().y_bytes());
8✔
189
      }
190
   }
191
#endif
192

193
   try {
29✔
194
      return key.get_int_field(field);
29✔
195
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
196
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
197
   }
4✔
198
}
199

200
}  // namespace
201

202
extern "C" {
203

204
using namespace Botan_FFI;
205

206
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
207
   if(field_name_cstr == nullptr) {
40✔
208
      return BOTAN_FFI_ERROR_NULL_POINTER;
209
   }
210

211
   const std::string field_name(field_name_cstr);
40✔
212

213
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
214
}
40✔
215

216
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
217
   if(field_name_cstr == nullptr) {
35✔
218
      return BOTAN_FFI_ERROR_NULL_POINTER;
219
   }
220

221
   const std::string field_name(field_name_cstr);
35✔
222

223
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
136✔
224
}
35✔
225

226
/* RSA specific operations */
227

228
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
2✔
229
   if(n_bits < 1024 || n_bits > 16 * 1024) {
2✔
230
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
231
   }
232

233
   const std::string n_str = std::to_string(n_bits);
2✔
234

235
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
2✔
236
}
2✔
237

238
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✔
239
#if defined(BOTAN_HAS_RSA)
240
   if(key == nullptr) {
2✔
241
      return BOTAN_FFI_ERROR_NULL_POINTER;
242
   }
243
   *key = nullptr;
2✔
244

245
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
246
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
2✔
247
      return ffi_new_object(key, std::move(rsa));
2✔
248
   });
3✔
249
#else
250
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
251
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
252
#endif
253
}
254

255
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
256
#if defined(BOTAN_HAS_RSA)
257
   if(Botan::any_null_pointers(key, bits)) {
1✔
258
      return BOTAN_FFI_ERROR_NULL_POINTER;
259
   }
260
   *key = nullptr;
1✔
261

262
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
263
      const Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
1✔
264
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, std::span{bits, len});
1✔
265
      return ffi_new_object(key, std::move(rsa));
2✔
266
   });
2✔
267
#else
268
   BOTAN_UNUSED(key, bits, len);
269
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
270
#endif
271
}
272

273
int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e) {
4✔
274
#if defined(BOTAN_HAS_RSA)
275
   if(key == nullptr) {
4✔
276
      return BOTAN_FFI_ERROR_NULL_POINTER;
277
   }
278
   *key = nullptr;
4✔
279
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
280
      auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
4✔
281
      return ffi_new_object(key, std::move(rsa));
3✔
282
   });
7✔
283
#else
284
   BOTAN_UNUSED(key, n, e);
285
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
286
#endif
287
}
288

289
int botan_pubkey_load_rsa_pkcs1(botan_pubkey_t* key, const uint8_t bits[], size_t len) {
×
290
#if defined(BOTAN_HAS_RSA)
291
   if(Botan::any_null_pointers(key, bits)) {
×
292
      return BOTAN_FFI_ERROR_NULL_POINTER;
293
   }
294
   *key = nullptr;
×
295

296
   return ffi_guard_thunk(__func__, [=]() -> int {
×
297
      const Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
×
298
      auto rsa = std::make_unique<Botan::RSA_PublicKey>(alg_id, std::span{bits, len});
×
299
      return ffi_new_object(key, std::move(rsa));
×
300
   });
×
301
#else
302
   BOTAN_UNUSED(key, bits, len);
303
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
304
#endif
305
}
306

307
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) {
1✔
308
   return botan_privkey_get_field(p, key, "p");
1✔
309
}
310

311
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) {
1✔
312
   return botan_privkey_get_field(q, key, "q");
1✔
313
}
314

315
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) {
1✔
316
   return botan_privkey_get_field(n, key, "n");
1✔
317
}
318

319
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
320
   return botan_privkey_get_field(e, key, "e");
1✔
321
}
322

323
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
1✔
324
   return botan_privkey_get_field(d, key, "d");
1✔
325
}
326

327
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
328
   return botan_pubkey_get_field(e, key, "e");
1✔
329
}
330

331
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
332
   return botan_pubkey_get_field(n, key, "n");
1✔
333
}
334

335
int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
4✔
336
#if defined(BOTAN_HAS_RSA)
337
   return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
14✔
338
      if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
339
         if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
340
            return write_vec_output(out, out_len, rsa->private_key_bits());
341
         } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
342
            // TODO define new generic functions for this
343
            return write_str_output(reinterpret_cast<char*>(out),
344
                                    out_len,
345
                                    Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
346
         } else {
347
            return BOTAN_FFI_ERROR_BAD_FLAG;
348
         }
349
      } else {
350
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
351
      }
352
   });
353
#else
354
   BOTAN_UNUSED(rsa_key, out, out_len, flags);
355
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
356
#endif
357
}
358

359
/* DSA specific operations */
360
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
361
#if defined(BOTAN_HAS_DSA)
362

363
   if(Botan::any_null_pointers(rng_obj, key)) {
1✔
364
      return BOTAN_FFI_ERROR_NULL_POINTER;
365
   }
366

367
   if((pbits % 64 != 0) || (qbits % 8 != 0) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
368
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
369
   }
370

371
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
372
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
373
      const Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
1✔
374
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
1✔
375
      return ffi_new_object(key, std::move(dsa));
1✔
376
   });
3✔
377
#else
378
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
379
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
380
#endif
381
}
382

383
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✔
384
#if defined(BOTAN_HAS_DSA)
385
   if(key == nullptr) {
2✔
386
      return BOTAN_FFI_ERROR_NULL_POINTER;
387
   }
388
   *key = nullptr;
2✔
389

390
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
391
      const Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
392
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
2✔
393
      return ffi_new_object(key, std::move(dsa));
2✔
394
   });
6✔
395
#else
396
   BOTAN_UNUSED(key, p, q, g, x);
397
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
398
#endif
399
}
400

401
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✔
402
#if defined(BOTAN_HAS_DSA)
403
   if(key == nullptr) {
2✔
404
      return BOTAN_FFI_ERROR_NULL_POINTER;
405
   }
406
   *key = nullptr;
2✔
407

408
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
409
      const Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
410
      auto dsa = std::make_unique<Botan::DSA_PublicKey>(group, safe_get(y));
2✔
411
      return ffi_new_object(key, std::move(dsa));
2✔
412
   });
6✔
413
#else
414
   BOTAN_UNUSED(key, p, q, g, y);
415
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
416
#endif
417
}
418

419
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
420
   return botan_privkey_get_field(x, key, "x");
2✔
421
}
422

423
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
2✔
424
   return botan_pubkey_get_field(p, key, "p");
2✔
425
}
426

427
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) {
2✔
428
   return botan_pubkey_get_field(q, key, "q");
2✔
429
}
430

431
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
432
   return botan_pubkey_get_field(g, key, "g");
2✔
433
}
434

435
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
436
   return botan_pubkey_get_field(y, key, "y");
2✔
437
}
438

439
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
440
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
441
}
442

443
/* ECDSA specific operations */
444

445
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key) {
9✔
446
#if defined(BOTAN_HAS_ECC_KEY)
447
   return ffi_guard_thunk(__func__, [=]() -> int {
9✔
448
      const Botan::Public_Key& pub_key = safe_get(key);
9✔
449
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
9✔
450

451
      if(ec_key == nullptr) {
9✔
452
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
453
      }
454

455
      return ec_key->domain().used_explicit_encoding() ? 1 : 0;
8✔
456
   });
9✔
457
#else
458
   BOTAN_UNUSED(key);
459
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
460
#endif
461
}
462

463
// NOLINTBEGIN(misc-misplaced-const)
464

465
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
466
                            const botan_mp_t public_x,
467
                            const botan_mp_t public_y,
468
                            const char* curve_name) {
469
#if defined(BOTAN_HAS_ECDSA)
470
   if(Botan::any_null_pointers(key, curve_name)) {
2✔
471
      return BOTAN_FFI_ERROR_NULL_POINTER;
472
   }
473
   *key = nullptr;
2✔
474

475
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
476
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
477

478
      const int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
479
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
480
         ffi_new_object(key, std::move(p_key));
2✔
481
      }
482

483
      return rc;
2✔
484
   });
4✔
485
#else
486
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
487
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
488
#endif
489
}
490

491
int botan_pubkey_load_ecdsa_sec1(botan_pubkey_t* key, const uint8_t sec1[], size_t sec1_len, const char* curve_name) {
3✔
492
#if defined(BOTAN_HAS_ECDSA)
493
   if(Botan::any_null_pointers(key, sec1, curve_name)) {
3✔
494
      return BOTAN_FFI_ERROR_NULL_POINTER;
495
   }
496
   *key = nullptr;
3✔
497

498
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
499
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
3✔
500

501
      const int rc = pubkey_load_ec_sec1(p_key, {sec1, sec1_len}, curve_name);
3✔
502
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
503
         ffi_new_object(key, std::move(p_key));
3✔
504
      }
505

506
      return rc;
3✔
507
   });
6✔
508
#else
509
   BOTAN_UNUSED(key, sec1, sec1_len, curve_name);
510
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
511
#endif
512
}
513

514
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
515
#if defined(BOTAN_HAS_ECDSA)
516
   if(Botan::any_null_pointers(key, curve_name)) {
2✔
517
      return BOTAN_FFI_ERROR_NULL_POINTER;
518
   }
519
   *key = nullptr;
2✔
520

521
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
522
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
2✔
523
      const int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
2✔
524
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
525
         ffi_new_object(key, std::move(p_key));
2✔
526
      }
527
      return rc;
2✔
528
   });
4✔
529
#else
530
   BOTAN_UNUSED(key, scalar, curve_name);
531
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
532
#endif
533
}
534

535
/* ElGamal specific operations */
536
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
537
#if defined(BOTAN_HAS_ELGAMAL)
538
   if(Botan::any_null_pointers(key, rng_obj)) {
1✔
539
      return BOTAN_FFI_ERROR_NULL_POINTER;
540
   }
541
   *key = nullptr;
1✔
542

543
   if(pbits < 1024 || qbits < 160) {
1✔
544
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
545
   }
546

547
   const Botan::DL_Group::PrimeType prime_type =
1✔
548
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
549

550
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
551
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
552
      const Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
553
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
554
      return ffi_new_object(key, std::move(elg));
1✔
555
   });
3✔
556
#else
557
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
558
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
559
#endif
560
}
561

562
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
2✔
563
#if defined(BOTAN_HAS_ELGAMAL)
564
   if(key == nullptr) {
2✔
565
      return BOTAN_FFI_ERROR_NULL_POINTER;
566
   }
567
   *key = nullptr;
2✔
568
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
569
      const Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
570
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
2✔
571
      return ffi_new_object(key, std::move(elg));
2✔
572
   });
6✔
573
#else
574
   BOTAN_UNUSED(key, p, g, y);
575
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
576
#endif
577
}
578

579
int botan_privkey_load_elgamal(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
2✔
580
#if defined(BOTAN_HAS_ELGAMAL)
581
   if(key == nullptr) {
2✔
582
      return BOTAN_FFI_ERROR_NULL_POINTER;
583
   }
584
   *key = nullptr;
2✔
585
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
586
      const Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
587
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(group, safe_get(x));
2✔
588
      return ffi_new_object(key, std::move(elg));
2✔
589
   });
6✔
590
#else
591
   BOTAN_UNUSED(key, p, g, x);
592
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
593
#endif
594
}
595

596
/* Diffie Hellman specific operations */
597

598
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
599
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
600
}
601

602
int botan_privkey_load_dh(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
1✔
603
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
604
   if(key == nullptr) {
1✔
605
      return BOTAN_FFI_ERROR_NULL_POINTER;
606
   }
607
   *key = nullptr;
1✔
608
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
609
      const Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
610
      auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
1✔
611
      return ffi_new_object(key, std::move(dh));
1✔
612
   });
3✔
613
#else
614
   BOTAN_UNUSED(key, p, g, x);
615
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
616
#endif
617
}
618

619
int botan_pubkey_load_dh(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
1✔
620
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
621
   if(key == nullptr) {
1✔
622
      return BOTAN_FFI_ERROR_NULL_POINTER;
623
   }
624
   *key = nullptr;
1✔
625
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
626
      const Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
627
      auto dh = std::make_unique<Botan::DH_PublicKey>(group, safe_get(y));
1✔
628
      return ffi_new_object(key, std::move(dh));
1✔
629
   });
3✔
630
#else
631
   BOTAN_UNUSED(key, p, g, y);
632
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
633
#endif
634
}
635

636
/* ECDH + x25519/x448 specific operations */
637

638
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
639
   if(Botan::any_null_pointers(key_obj, param_str)) {
2✔
640
      return BOTAN_FFI_ERROR_NULL_POINTER;
641
   }
642
   *key_obj = nullptr;
2✔
643

644
   const std::string params(param_str);
2✔
645

646
   if(params == "X25519" || params == "x25519" || params == "curve25519") {
2✔
647
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
648
   }
649

650
   if(params == "X448" || params == "x448") {
2✔
651
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
652
   }
653

654
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
655
}
2✔
656

657
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
658
                           const botan_mp_t public_x,
659
                           const botan_mp_t public_y,
660
                           const char* curve_name) {
661
#if defined(BOTAN_HAS_ECDH)
662
   if(Botan::any_null_pointers(key, curve_name)) {
1✔
663
      return BOTAN_FFI_ERROR_NULL_POINTER;
664
   }
665
   *key = nullptr;
1✔
666
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
667
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
668
      const int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
669

670
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
671
         ffi_new_object(key, std::move(p_key));
1✔
672
      }
673
      return rc;
1✔
674
   });
2✔
675
#else
676
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
677
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
678
#endif
679
}
680

681
int botan_pubkey_load_ecdh_sec1(botan_pubkey_t* key, const uint8_t sec1[], size_t sec1_len, const char* curve_name) {
7✔
682
#if defined(BOTAN_HAS_ECDH)
683
   if(Botan::any_null_pointers(key, sec1, curve_name)) {
7✔
684
      return BOTAN_FFI_ERROR_NULL_POINTER;
685
   }
686
   *key = nullptr;
7✔
687

688
   return ffi_guard_thunk(__func__, [=]() -> int {
7✔
689
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
7✔
690

691
      const int rc = pubkey_load_ec_sec1(p_key, {sec1, sec1_len}, curve_name);
7✔
692
      if(rc == BOTAN_FFI_SUCCESS) {
7✔
693
         ffi_new_object(key, std::move(p_key));
7✔
694
      }
695

696
      return rc;
7✔
697
   });
14✔
698
#else
699
   BOTAN_UNUSED(key, sec1, sec1_len, curve_name);
700
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
701
#endif
702
}
703

704
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
4✔
705
#if defined(BOTAN_HAS_ECDH)
706
   if(Botan::any_null_pointers(key, curve_name)) {
4✔
707
      return BOTAN_FFI_ERROR_NULL_POINTER;
708
   }
709
   *key = nullptr;
4✔
710
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
711
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
4✔
712
      const int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
4✔
713
      if(rc == BOTAN_FFI_SUCCESS) {
4✔
714
         ffi_new_object(key, std::move(p_key));
4✔
715
      }
716
      return rc;
4✔
717
   });
8✔
718
#else
719
   BOTAN_UNUSED(key, scalar, curve_name);
720
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
721
#endif
722
}
723

724
/* SM2 specific operations */
725

726
int botan_pubkey_sm2_compute_za(
2✔
727
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
728
   if(Botan::any_null_pointers(out, out_len, ident, hash_algo, key)) {
2✔
729
      return BOTAN_FFI_ERROR_NULL_POINTER;
730
   }
731

732
#if defined(BOTAN_HAS_SM2)
733
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
734
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
735
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
736

737
      if(ec_key == nullptr) {
2✔
738
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
739
      }
740

741
      if(ec_key->algo_name() != "SM2") {
2✔
742
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
743
      }
744

745
      const std::string ident_str(ident);
2✔
746
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
747

748
      const auto& pt = ec_key->_public_ec_point();
2✔
749

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

752
      return write_vec_output(out, out_len, za);
2✔
753
   });
6✔
754
#else
755
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
756
#endif
757
}
758

759
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
760
                          const botan_mp_t public_x,
761
                          const botan_mp_t public_y,
762
                          const char* curve_name) {
763
#if defined(BOTAN_HAS_SM2)
764
   if(Botan::any_null_pointers(key, curve_name)) {
3✔
765
      return BOTAN_FFI_ERROR_NULL_POINTER;
766
   }
767
   *key = nullptr;
3✔
768

769
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
770
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
3✔
771
      if(pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name) == 0) {
3✔
772
         return ffi_new_object(key, std::move(p_key));
3✔
773
      } else {
774
         return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
775
      }
776
   });
6✔
777
#else
778
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
779
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
780
#endif
781
}
782

783
int botan_pubkey_load_sm2_sec1(botan_pubkey_t* key, const uint8_t sec1[], size_t sec1_len, const char* curve_name) {
4✔
784
#if defined(BOTAN_HAS_SM2)
785
   if(Botan::any_null_pointers(key, sec1, curve_name)) {
4✔
786
      return BOTAN_FFI_ERROR_NULL_POINTER;
787
   }
788
   *key = nullptr;
4✔
789

790
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
791
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
4✔
792

793
      const int rc = pubkey_load_ec_sec1(p_key, {sec1, sec1_len}, curve_name);
4✔
794
      if(rc == BOTAN_FFI_SUCCESS) {
4✔
795
         ffi_new_object(key, std::move(p_key));
4✔
796
      }
797

798
      return rc;
4✔
799
   });
8✔
800
#else
801
   BOTAN_UNUSED(key, sec1, sec1_len, curve_name);
802
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
803
#endif
804
}
805

806
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
807
#if defined(BOTAN_HAS_SM2)
808
   if(Botan::any_null_pointers(key, curve_name)) {
3✔
809
      return BOTAN_FFI_ERROR_NULL_POINTER;
810
   }
811
   *key = nullptr;
3✔
812

813
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
814
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
815
      const int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
816

817
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
818
         ffi_new_object(key, std::move(p_key));
3✔
819
      }
820
      return rc;
3✔
821
   });
6✔
822
#else
823
   BOTAN_UNUSED(key, scalar, curve_name);
824
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
825
#endif
826
}
827

828
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
829
                              const botan_mp_t public_x,
830
                              const botan_mp_t public_y,
831
                              const char* curve_name) {
832
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
833
}
834

835
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
836
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
837
}
838

839
/* EC key specific operations */
840

841
int botan_ec_privkey_get_private_key(botan_privkey_t key, botan_ec_scalar_t* value) {
2✔
842
   if(Botan::any_null_pointers(value)) {
2✔
843
      return BOTAN_FFI_ERROR_NULL_POINTER;
844
   }
845
#if defined(BOTAN_HAS_ECC_KEY)
846
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
847
      const Botan::EC_PrivateKey* ec_key = dynamic_cast<const Botan::EC_PrivateKey*>(&safe_get(key));
4✔
848
      if(ec_key == nullptr) {
2✔
849
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
850
      }
851
      return ffi_new_object(value, std::make_unique<Botan::EC_Scalar>(ec_key->_private_key()));
2✔
852
   });
2✔
853
#else
854
   BOTAN_UNUSED(key, value);
855
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
856
#endif
857
}
858

859
int botan_ec_privkey_get_group(botan_privkey_t key, botan_ec_group_t* ec_group) {
2✔
860
   if(Botan::any_null_pointers(ec_group)) {
2✔
861
      return BOTAN_FFI_ERROR_NULL_POINTER;
862
   }
863

864
#if defined(BOTAN_HAS_ECC_KEY)
865
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
866
      const Botan::EC_PrivateKey* ec_key = dynamic_cast<const Botan::EC_PrivateKey*>(&safe_get(key));
4✔
867
      if(ec_key == nullptr) {
2✔
868
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
869
      }
870
      return ffi_new_object(ec_group, std::make_unique<Botan::EC_Group>(ec_key->domain()));
2✔
871
   });
2✔
872
#else
873
   BOTAN_UNUSED(key, ec_group);
874
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
875
#endif
876
}
877

878
int botan_ec_pubkey_get_group(botan_pubkey_t key, botan_ec_group_t* ec_group) {
1✔
879
   if(Botan::any_null_pointers(ec_group)) {
1✔
880
      return BOTAN_FFI_ERROR_NULL_POINTER;
881
   }
882
#if defined(BOTAN_HAS_ECC_KEY)
883
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
884
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&safe_get(key));
2✔
885
      if(ec_key == nullptr) {
1✔
886
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
887
      }
888
      return ffi_new_object(ec_group, std::make_unique<Botan::EC_Group>(ec_key->domain()));
1✔
889
   });
1✔
890
#else
891
   BOTAN_UNUSED(key, ec_group);
892
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
893
#endif
894
}
895

896
/* Ed25519 specific operations */
897

898
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
899
#if defined(BOTAN_HAS_ED25519)
900
   if(key == nullptr) {
1✔
901
      return BOTAN_FFI_ERROR_NULL_POINTER;
902
   }
903
   *key = nullptr;
1✔
904
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
905
      auto ed25519 =
1✔
906
         std::make_unique<Botan::Ed25519_PrivateKey>(Botan::Ed25519_PrivateKey::from_seed(std::span{privkey, 32}));
2✔
907
      return ffi_new_object(key, std::move(ed25519));
2✔
908
   });
2✔
909
#else
910
   BOTAN_UNUSED(key, privkey);
911
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
912
#endif
913
}
914

915
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
916
#if defined(BOTAN_HAS_ED25519)
917
   if(key == nullptr) {
1✔
918
      return BOTAN_FFI_ERROR_NULL_POINTER;
919
   }
920
   *key = nullptr;
1✔
921
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
922
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
923
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
924
      return ffi_new_object(key, std::move(ed25519));
1✔
925
   });
3✔
926
#else
927
   BOTAN_UNUSED(key, pubkey);
928
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
929
#endif
930
}
931

932
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
933
   if(output == nullptr) {
1✔
934
      return BOTAN_FFI_ERROR_NULL_POINTER;
935
   }
936
#if defined(BOTAN_HAS_ED25519)
937
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
938
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
939
         const auto ed_key = ed->raw_private_key_bits();
940
         if(ed_key.size() != 64) {
941
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
942
         }
943
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
944
         return BOTAN_FFI_SUCCESS;
945
      } else {
946
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
947
      }
948
   });
949
#else
950
   BOTAN_UNUSED(key, output);
951
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
952
#endif
953
}
954

955
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
956
   if(output == nullptr) {
1✔
957
      return BOTAN_FFI_ERROR_NULL_POINTER;
958
   }
959
#if defined(BOTAN_HAS_ED25519)
960
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
961
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
962
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
963
         if(ed_key.size() != 32) {
964
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
965
         }
966
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
967
         return BOTAN_FFI_SUCCESS;
968
      } else {
969
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
970
      }
971
   });
972
#else
973
   BOTAN_UNUSED(key, output);
974
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
975
#endif
976
}
977

978
/* Ed448 specific operations */
979

980
int botan_privkey_load_ed448(botan_privkey_t* key, const uint8_t privkey[57]) {
1✔
981
#if defined(BOTAN_HAS_ED448)
982
   if(key == nullptr) {
1✔
983
      return BOTAN_FFI_ERROR_NULL_POINTER;
984
   }
985
   *key = nullptr;
1✔
986
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
987
      auto ed448 = std::make_unique<Botan::Ed448_PrivateKey>(std::span(privkey, 57));
1✔
988
      return ffi_new_object(key, std::move(ed448));
2✔
989
   });
2✔
990
#else
991
   BOTAN_UNUSED(key, privkey);
992
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
993
#endif
994
}
995

996
int botan_pubkey_load_ed448(botan_pubkey_t* key, const uint8_t pubkey[57]) {
1✔
997
#if defined(BOTAN_HAS_ED448)
998
   if(key == nullptr) {
1✔
999
      return BOTAN_FFI_ERROR_NULL_POINTER;
1000
   }
1001
   *key = nullptr;
1✔
1002
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1003
      auto ed448 = std::make_unique<Botan::Ed448_PublicKey>(std::span(pubkey, 57));
1✔
1004
      return ffi_new_object(key, std::move(ed448));
1✔
1005
   });
2✔
1006
#else
1007
   BOTAN_UNUSED(key, pubkey);
1008
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1009
#endif
1010
}
1011

1012
int botan_privkey_ed448_get_privkey(botan_privkey_t key, uint8_t output[57]) {
1✔
1013
   if(output == nullptr) {
1✔
1014
      return BOTAN_FFI_ERROR_NULL_POINTER;
1015
   }
1016
#if defined(BOTAN_HAS_ED448)
1017
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
1018
      if(auto ed = dynamic_cast<const Botan::Ed448_PrivateKey*>(&k)) {
1019
         const auto ed_key = ed->raw_private_key_bits();
1020
         Botan::copy_mem(std::span(output, 57), ed_key);
1021
         return BOTAN_FFI_SUCCESS;
1022
      } else {
1023
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1024
      }
1025
   });
1026
#else
1027
   BOTAN_UNUSED(key, output);
1028
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1029
#endif
1030
}
1031

1032
int botan_pubkey_ed448_get_pubkey(botan_pubkey_t key, uint8_t output[57]) {
1✔
1033
   if(output == nullptr) {
1✔
1034
      return BOTAN_FFI_ERROR_NULL_POINTER;
1035
   }
1036
#if defined(BOTAN_HAS_ED448)
1037
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
3✔
1038
      if(auto ed = dynamic_cast<const Botan::Ed448_PublicKey*>(&k)) {
1039
         const auto ed_key = ed->public_key_bits();
1040
         Botan::copy_mem(std::span(output, 57), ed_key);
1041
         return BOTAN_FFI_SUCCESS;
1042
      } else {
1043
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1044
      }
1045
   });
1046
#else
1047
   BOTAN_UNUSED(key, output);
1048
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1049
#endif
1050
}
1051

1052
/* X25519 specific operations */
1053

1054
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
1055
#if defined(BOTAN_HAS_X25519)
1056
   if(key == nullptr) {
1✔
1057
      return BOTAN_FFI_ERROR_NULL_POINTER;
1058
   }
1059
   *key = nullptr;
1✔
1060
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1061
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(std::span{privkey, 32});
1✔
1062
      return ffi_new_object(key, std::move(x25519));
2✔
1063
   });
2✔
1064
#else
1065
   BOTAN_UNUSED(key, privkey);
1066
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1067
#endif
1068
}
1069

1070
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
1071
#if defined(BOTAN_HAS_X25519)
1072
   if(key == nullptr) {
1✔
1073
      return BOTAN_FFI_ERROR_NULL_POINTER;
1074
   }
1075
   *key = nullptr;
1✔
1076
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1077
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(std::span{pubkey, 32});
1✔
1078
      return ffi_new_object(key, std::move(x25519));
1✔
1079
   });
2✔
1080
#else
1081
   BOTAN_UNUSED(key, pubkey);
1082
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1083
#endif
1084
}
1085

1086
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
1087
   if(output == nullptr) {
1✔
1088
      return BOTAN_FFI_ERROR_NULL_POINTER;
1089
   }
1090
#if defined(BOTAN_HAS_X25519)
1091
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
1092
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
1093
         const auto x25519_key = x25519->raw_private_key_bits();
1094
         if(x25519_key.size() != 32) {
1095
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
1096
         }
1097
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
1098
         return BOTAN_FFI_SUCCESS;
1099
      } else {
1100
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1101
      }
1102
   });
1103
#else
1104
   BOTAN_UNUSED(key, output);
1105
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1106
#endif
1107
}
1108

1109
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
1110
   if(output == nullptr) {
2✔
1111
      return BOTAN_FFI_ERROR_NULL_POINTER;
1112
   }
1113
#if defined(BOTAN_HAS_X25519)
1114
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
6✔
1115
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
1116
         Botan::copy_mem(std::span{output, 32}, x25519->raw_public_key_bits());
1117
         return BOTAN_FFI_SUCCESS;
1118
      } else {
1119
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1120
      }
1121
   });
1122
#else
1123
   BOTAN_UNUSED(key, output);
1124
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1125
#endif
1126
}
1127

1128
/* X448 specific operations */
1129

1130
int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
1✔
1131
#if defined(BOTAN_HAS_X448)
1132
   if(key == nullptr) {
1✔
1133
      return BOTAN_FFI_ERROR_NULL_POINTER;
1134
   }
1135
   *key = nullptr;
1✔
1136
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1137
      auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span{privkey, 56});
1✔
1138
      return ffi_new_object(key, std::move(x448));
2✔
1139
   });
2✔
1140
#else
1141
   BOTAN_UNUSED(key, privkey);
1142
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1143
#endif
1144
}
1145

1146
int botan_pubkey_load_x448(botan_pubkey_t* key, const uint8_t pubkey[56]) {
1✔
1147
#if defined(BOTAN_HAS_X448)
1148
   if(key == nullptr) {
1✔
1149
      return BOTAN_FFI_ERROR_NULL_POINTER;
1150
   }
1151
   *key = nullptr;
1✔
1152
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1153
      auto x448 = std::make_unique<Botan::X448_PublicKey>(std::span{pubkey, 56});
1✔
1154
      return ffi_new_object(key, std::move(x448));
1✔
1155
   });
2✔
1156
#else
1157
   BOTAN_UNUSED(key, pubkey);
1158
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1159
#endif
1160
}
1161

1162
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56]) {
1✔
1163
   if(output == nullptr) {
1✔
1164
      return BOTAN_FFI_ERROR_NULL_POINTER;
1165
   }
1166
#if defined(BOTAN_HAS_X448)
1167
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
1168
      if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
1169
         const auto x448_key = x448->raw_private_key_bits();
1170
         Botan::copy_mem(std::span{output, 56}, x448_key);
1171
         return BOTAN_FFI_SUCCESS;
1172
      } else {
1173
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1174
      }
1175
   });
1176
#else
1177
   BOTAN_UNUSED(key, output);
1178
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1179
#endif
1180
}
1181

1182
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
2✔
1183
   if(output == nullptr) {
2✔
1184
      return BOTAN_FFI_ERROR_NULL_POINTER;
1185
   }
1186
#if defined(BOTAN_HAS_X448)
1187
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
6✔
1188
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
1189
         Botan::copy_mem(std::span{output, 56}, x448->raw_public_key_bits());
1190
         return BOTAN_FFI_SUCCESS;
1191
      } else {
1192
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1193
      }
1194
   });
1195
#else
1196
   BOTAN_UNUSED(key, output);
1197
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1198
#endif
1199
}
1200

1201
/*
1202
* Algorithm specific key operations: Kyber
1203
*/
1204

1205
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
1206
#if defined(BOTAN_HAS_KYBER)
1207
   if(Botan::any_null_pointers(key, privkey)) {
4✔
1208
      return BOTAN_FFI_ERROR_NULL_POINTER;
1209
   }
1210
   *key = nullptr;
4✔
1211

1212
   const auto mode = [](size_t len) -> std::optional<Botan::KyberMode> {
12✔
1213
      if(len == 1632) {
4✔
1214
         return Botan::KyberMode::Kyber512_R3;
1✔
1215
      } else if(len == 2400) {
3✔
1216
         return Botan::KyberMode::Kyber768_R3;
2✔
1217
      } else if(len == 3168) {
1✔
1218
         return Botan::KyberMode::Kyber1024_R3;
1✔
1219
      } else {
1220
         return {};
×
1221
      }
1222
   }(key_len);
4✔
1223

1224
   if(mode.has_value()) {
4✔
1225
      return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1226
         auto kyber = std::make_unique<Botan::Kyber_PrivateKey>(std::span{privkey, key_len}, *mode);
4✔
1227
         return ffi_new_object(key, std::move(kyber));
8✔
1228
      });
4✔
1229
   } else {
1230
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
1231
   }
1232
#else
1233
   BOTAN_UNUSED(key, key_len, privkey);
1234
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1235
#endif
1236
}
1237

1238
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
1239
#if defined(BOTAN_HAS_KYBER)
1240
   if(Botan::any_null_pointers(key, pubkey)) {
4✔
1241
      return BOTAN_FFI_ERROR_NULL_POINTER;
1242
   }
1243
   *key = nullptr;
4✔
1244

1245
   const auto mode = [](size_t len) -> std::optional<Botan::KyberMode> {
12✔
1246
      if(len == 800) {
4✔
1247
         return Botan::KyberMode::Kyber512_R3;
1✔
1248
      } else if(len == 1184) {
3✔
1249
         return Botan::KyberMode::Kyber768_R3;
2✔
1250
      } else if(len == 1568) {
1✔
1251
         return Botan::KyberMode::Kyber1024_R3;
1✔
1252
      } else {
1253
         return {};
×
1254
      }
1255
   }(key_len);
4✔
1256

1257
   if(mode.has_value()) {
4✔
1258
      return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1259
         auto kyber = std::make_unique<Botan::Kyber_PublicKey>(std::span{pubkey, key_len}, *mode);
4✔
1260
         return ffi_new_object(key, std::move(kyber));
4✔
1261
      });
4✔
1262
   } else {
1263
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
1264
   }
1265
#else
1266
   BOTAN_UNUSED(key, pubkey, key_len);
1267
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1268
#endif
1269
}
1270

1271
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1272
#if defined(BOTAN_HAS_KYBER)
1273
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
16✔
1274
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1275
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1276
      } else {
1277
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1278
      }
1279
   });
1280
#else
1281
   BOTAN_UNUSED(key, ctx, view);
1282
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1283
#endif
1284
}
1285

1286
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1287
#if defined(BOTAN_HAS_KYBER)
1288
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
32✔
1289
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1290
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1291
      } else {
1292
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1293
      }
1294
   });
1295
#else
1296
   BOTAN_UNUSED(key, ctx, view);
1297
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1298
#endif
1299
}
1300

1301
/*
1302
* Algorithm specific key operations: ML-KEM
1303
*/
1304

1305
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1306
#if defined(BOTAN_HAS_ML_KEM)
1307
   if(Botan::any_null_pointers(key, privkey, mlkem_mode)) {
4✔
1308
      return BOTAN_FFI_ERROR_NULL_POINTER;
1309
   }
1310

1311
   *key = nullptr;
4✔
1312

1313
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1314
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1315
      if(!mode.is_ml_kem()) {
4✔
1316
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1317
      }
1318

1319
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1320
      return ffi_new_object(key, std::move(mlkem_key));
4✔
1321
   });
8✔
1322
#else
1323
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1324
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1325
#endif
1326
}
1327

1328
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
4✔
1329
#if defined(BOTAN_HAS_ML_KEM)
1330
   if(Botan::any_null_pointers(key, pubkey, mlkem_mode)) {
4✔
1331
      return BOTAN_FFI_ERROR_NULL_POINTER;
1332
   }
1333

1334
   *key = nullptr;
4✔
1335

1336
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1337
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1338
      if(!mode.is_ml_kem()) {
4✔
1339
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1340
      }
1341

1342
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PublicKey>(std::span{pubkey, key_len}, mode.mode());
4✔
1343
      return ffi_new_object(key, std::move(mlkem_key));
4✔
1344
   });
8✔
1345
#else
1346
   BOTAN_UNUSED(key, key_len, pubkey, mlkem_mode);
1347
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1348
#endif
1349
}
1350

1351
/*
1352
* Algorithm specific key operations: ML-DSA
1353
*/
1354

1355
int botan_privkey_load_ml_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mldsa_mode) {
4✔
1356
#if defined(BOTAN_HAS_ML_DSA)
1357
   if(Botan::any_null_pointers(key, privkey, mldsa_mode)) {
4✔
1358
      return BOTAN_FFI_ERROR_NULL_POINTER;
1359
   }
1360

1361
   *key = nullptr;
4✔
1362

1363
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1364
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1365
      if(!mode.is_ml_dsa()) {
4✔
1366
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1367
      }
1368

1369
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1370
      return ffi_new_object(key, std::move(mldsa_key));
4✔
1371
   });
8✔
1372
#else
1373
   BOTAN_UNUSED(key, key_len, privkey, mldsa_mode);
1374
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1375
#endif
1376
}
1377

1378
int botan_pubkey_load_ml_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mldsa_mode) {
4✔
1379
#if defined(BOTAN_HAS_ML_DSA)
1380
   if(Botan::any_null_pointers(key, pubkey, mldsa_mode)) {
4✔
1381
      return BOTAN_FFI_ERROR_NULL_POINTER;
1382
   }
1383

1384
   *key = nullptr;
4✔
1385

1386
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1387
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1388
      if(!mode.is_ml_dsa()) {
4✔
1389
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1390
      }
1391

1392
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
4✔
1393
      return ffi_new_object(key, std::move(mldsa_key));
4✔
1394
   });
8✔
1395
#else
1396
   BOTAN_UNUSED(key, key_len, pubkey, mldsa_mode);
1397
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1398
#endif
1399
}
1400

1401
/*
1402
* Algorithm specific key operations: SLH-DSA
1403
*/
1404

1405
int botan_privkey_load_slh_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1406
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1407
   if(Botan::any_null_pointers(key, privkey, slhdsa_mode)) {
13✔
1408
      return BOTAN_FFI_ERROR_NULL_POINTER;
1409
   }
1410

1411
   *key = nullptr;
13✔
1412

1413
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1414
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1415
      if(!mode.is_slh_dsa()) {
13✔
1416
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1417
      }
1418

1419
      auto slhdsa_key = std::make_unique<Botan::SLH_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1420
      return ffi_new_object(key, std::move(slhdsa_key));
26✔
1421
   });
26✔
1422
#else
1423
   BOTAN_UNUSED(key, key_len, privkey, slhdsa_mode);
1424
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1425
#endif
1426
}
1427

1428
int botan_pubkey_load_slh_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1429
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1430
   if(Botan::any_null_pointers(key, pubkey, slhdsa_mode)) {
13✔
1431
      return BOTAN_FFI_ERROR_NULL_POINTER;
1432
   }
1433

1434
   *key = nullptr;
13✔
1435

1436
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1437
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1438
      if(!mode.is_slh_dsa()) {
13✔
1439
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1440
      }
1441

1442
      auto mldsa_key = std::make_unique<Botan::SLH_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1443
      return ffi_new_object(key, std::move(mldsa_key));
13✔
1444
   });
26✔
1445
#else
1446
   BOTAN_UNUSED(key, key_len, pubkey, slhdsa_mode);
1447
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1448
#endif
1449
}
1450

1451
/*
1452
* Algorithm specific key operations: FrodoKEM
1453
*/
1454

1455
int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* frodo_mode) {
13✔
1456
#if defined(BOTAN_HAS_FRODOKEM)
1457
   if(Botan::any_null_pointers(key, privkey, frodo_mode)) {
13✔
1458
      return BOTAN_FFI_ERROR_NULL_POINTER;
1459
   }
1460

1461
   *key = nullptr;
13✔
1462

1463
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1464
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1465
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1466
      return ffi_new_object(key, std::move(frodo_key));
26✔
1467
   });
26✔
1468
#else
1469
   BOTAN_UNUSED(key, privkey, key_len, frodo_mode);
1470
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1471
#endif
1472
}
1473

1474
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode) {
13✔
1475
#if defined(BOTAN_HAS_FRODOKEM)
1476
   if(Botan::any_null_pointers(key, pubkey, frodo_mode)) {
13✔
1477
      return BOTAN_FFI_ERROR_NULL_POINTER;
1478
   }
1479

1480
   *key = nullptr;
13✔
1481

1482
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1483
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1484
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1485
      return ffi_new_object(key, std::move(frodo_key));
13✔
1486
   });
26✔
1487
#else
1488
   BOTAN_UNUSED(key, pubkey, key_len, frodo_mode);
1489
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1490
#endif
1491
}
1492

1493
/*
1494
* Algorithm specific key operations : Classic McEliece
1495
*/
1496

1497
int botan_privkey_load_classic_mceliece(botan_privkey_t* key,
17✔
1498
                                        const uint8_t privkey[],
1499
                                        size_t key_len,
1500
                                        const char* cmce_mode) {
1501
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1502
   if(Botan::any_null_pointers(key, privkey, cmce_mode)) {
17✔
1503
      return BOTAN_FFI_ERROR_NULL_POINTER;
1504
   }
1505

1506
   *key = nullptr;
17✔
1507

1508
   return ffi_guard_thunk(__func__, [=]() -> int {
17✔
1509
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1510
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PrivateKey>(std::span{privkey, key_len}, mode);
17✔
1511
      return ffi_new_object(key, std::move(cmce_key));
34✔
1512
   });
34✔
1513
#else
1514
   BOTAN_UNUSED(key, privkey, key_len, cmce_mode);
1515
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1516
#endif
1517
}
1518

1519
int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
17✔
1520
                                       const uint8_t pubkey[],
1521
                                       size_t key_len,
1522
                                       const char* cmce_mode) {
1523
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1524
   if(Botan::any_null_pointers(key, pubkey, cmce_mode)) {
17✔
1525
      return BOTAN_FFI_ERROR_NULL_POINTER;
1526
   }
1527

1528
   *key = nullptr;
17✔
1529

1530
   return ffi_guard_thunk(__func__, [=]() -> int {
17✔
1531
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1532
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PublicKey>(std::span{pubkey, key_len}, mode);
17✔
1533
      return ffi_new_object(key, std::move(cmce_key));
17✔
1534
   });
34✔
1535
#else
1536
   BOTAN_UNUSED(key, pubkey, key_len, cmce_mode);
1537
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1538
#endif
1539
}
1540

1541
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
7✔
1542
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1543
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
28✔
1544
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1545
         auto pt = ecc->_public_ec_point().serialize_uncompressed();
1546
         return invoke_view_callback(view, ctx, pt);
1547
      } else {
1548
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1549
      }
1550
   });
1551
#else
1552
   BOTAN_UNUSED(key, view, ctx);
1553
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1554
#endif
1555
}
1556

1557
// NOLINTEND(misc-misplaced-const)
1558

1559
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1560
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1561
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1562
}
1✔
1563

1564
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1565
                         const char* aead,
1566
                         const uint8_t ct[],
1567
                         size_t ct_len,
1568
                         const uint8_t ad[],
1569
                         size_t ad_len,
1570
                         uint8_t out[],
1571
                         size_t* out_len) {
1572
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1573
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1574
}
1575

1576
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1577
                         botan_rng_t rng_obj,
1578
                         const char* aead,
1579
                         const uint8_t pt[],
1580
                         size_t pt_len,
1581
                         const uint8_t ad[],
1582
                         size_t ad_len,
1583
                         uint8_t out[],
1584
                         size_t* out_len) {
1585
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1586
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1587
}
1588
}
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