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

randombit / botan / 23992310984

05 Apr 2026 02:14AM UTC coverage: 89.447% (-0.007%) from 89.454%
23992310984

Pull #5521

github

web-flow
Merge c18078031 into 417709dd7
Pull Request #5521: Rollup of small fixes

105767 of 118245 relevant lines covered (89.45%)

11566159.12 hits per line

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

96.59
/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_mp.h>
17
#include <botan/internal/ffi_pkey.h>
18
#include <botan/internal/ffi_rng.h>
19
#include <botan/internal/ffi_util.h>
20

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

97
namespace {
98

99
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
100

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

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

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

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

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

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

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

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

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

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

159
#endif
160

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

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

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

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

199
}  // namespace
200

201
extern "C" {
202

203
using namespace Botan_FFI;
204

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

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

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

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

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

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

225
/* RSA specific operations */
226

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

442
/* ECDSA specific operations */
443

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

595
/* Diffie Hellman specific operations */
596

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

723
/* SM2 specific operations */
724

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

838
/* Ed25519 specific operations */
839

840
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
841
#if defined(BOTAN_HAS_ED25519)
842
   if(key == nullptr) {
1✔
843
      return BOTAN_FFI_ERROR_NULL_POINTER;
844
   }
845
   *key = nullptr;
1✔
846
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
847
      auto ed25519 =
1✔
848
         std::make_unique<Botan::Ed25519_PrivateKey>(Botan::Ed25519_PrivateKey::from_seed(std::span{privkey, 32}));
2✔
849
      return ffi_new_object(key, std::move(ed25519));
2✔
850
   });
2✔
851
#else
852
   BOTAN_UNUSED(key, privkey);
853
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
854
#endif
855
}
856

857
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
858
#if defined(BOTAN_HAS_ED25519)
859
   if(key == nullptr) {
1✔
860
      return BOTAN_FFI_ERROR_NULL_POINTER;
861
   }
862
   *key = nullptr;
1✔
863
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
864
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
865
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
866
      return ffi_new_object(key, std::move(ed25519));
1✔
867
   });
3✔
868
#else
869
   BOTAN_UNUSED(key, pubkey);
870
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
871
#endif
872
}
873

874
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
875
   if(output == nullptr) {
1✔
876
      return BOTAN_FFI_ERROR_NULL_POINTER;
877
   }
878
#if defined(BOTAN_HAS_ED25519)
879
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
880
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
881
         const auto ed_key = ed->raw_private_key_bits();
882
         if(ed_key.size() != 64) {
883
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
884
         }
885
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
886
         return BOTAN_FFI_SUCCESS;
887
      } else {
888
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
889
      }
890
   });
891
#else
892
   BOTAN_UNUSED(key, output);
893
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
894
#endif
895
}
896

897
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
898
   if(output == nullptr) {
1✔
899
      return BOTAN_FFI_ERROR_NULL_POINTER;
900
   }
901
#if defined(BOTAN_HAS_ED25519)
902
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
903
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
904
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
905
         if(ed_key.size() != 32) {
906
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
907
         }
908
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
909
         return BOTAN_FFI_SUCCESS;
910
      } else {
911
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
912
      }
913
   });
914
#else
915
   BOTAN_UNUSED(key, output);
916
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
917
#endif
918
}
919

920
/* Ed448 specific operations */
921

922
int botan_privkey_load_ed448(botan_privkey_t* key, const uint8_t privkey[57]) {
1✔
923
#if defined(BOTAN_HAS_ED448)
924
   if(key == nullptr) {
1✔
925
      return BOTAN_FFI_ERROR_NULL_POINTER;
926
   }
927
   *key = nullptr;
1✔
928
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
929
      auto ed448 = std::make_unique<Botan::Ed448_PrivateKey>(std::span(privkey, 57));
1✔
930
      return ffi_new_object(key, std::move(ed448));
2✔
931
   });
2✔
932
#else
933
   BOTAN_UNUSED(key, privkey);
934
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
935
#endif
936
}
937

938
int botan_pubkey_load_ed448(botan_pubkey_t* key, const uint8_t pubkey[57]) {
1✔
939
#if defined(BOTAN_HAS_ED448)
940
   if(key == nullptr) {
1✔
941
      return BOTAN_FFI_ERROR_NULL_POINTER;
942
   }
943
   *key = nullptr;
1✔
944
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
945
      auto ed448 = std::make_unique<Botan::Ed448_PublicKey>(std::span(pubkey, 57));
1✔
946
      return ffi_new_object(key, std::move(ed448));
1✔
947
   });
2✔
948
#else
949
   BOTAN_UNUSED(key, pubkey);
950
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
951
#endif
952
}
953

954
int botan_privkey_ed448_get_privkey(botan_privkey_t key, uint8_t output[57]) {
1✔
955
   if(output == nullptr) {
1✔
956
      return BOTAN_FFI_ERROR_NULL_POINTER;
957
   }
958
#if defined(BOTAN_HAS_ED448)
959
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
960
      if(auto ed = dynamic_cast<const Botan::Ed448_PrivateKey*>(&k)) {
961
         const auto ed_key = ed->raw_private_key_bits();
962
         Botan::copy_mem(std::span(output, 57), ed_key);
963
         return BOTAN_FFI_SUCCESS;
964
      } else {
965
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
966
      }
967
   });
968
#else
969
   BOTAN_UNUSED(key, output);
970
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
971
#endif
972
}
973

974
int botan_pubkey_ed448_get_pubkey(botan_pubkey_t key, uint8_t output[57]) {
1✔
975
   if(output == nullptr) {
1✔
976
      return BOTAN_FFI_ERROR_NULL_POINTER;
977
   }
978
#if defined(BOTAN_HAS_ED448)
979
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
3✔
980
      if(auto ed = dynamic_cast<const Botan::Ed448_PublicKey*>(&k)) {
981
         const auto ed_key = ed->public_key_bits();
982
         Botan::copy_mem(std::span(output, 57), ed_key);
983
         return BOTAN_FFI_SUCCESS;
984
      } else {
985
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
986
      }
987
   });
988
#else
989
   BOTAN_UNUSED(key, output);
990
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
991
#endif
992
}
993

994
/* X25519 specific operations */
995

996
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
997
#if defined(BOTAN_HAS_X25519)
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 x25519 = std::make_unique<Botan::X25519_PrivateKey>(std::span{privkey, 32});
1✔
1004
      return ffi_new_object(key, std::move(x25519));
2✔
1005
   });
2✔
1006
#else
1007
   BOTAN_UNUSED(key, privkey);
1008
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1009
#endif
1010
}
1011

1012
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
1013
#if defined(BOTAN_HAS_X25519)
1014
   if(key == nullptr) {
1✔
1015
      return BOTAN_FFI_ERROR_NULL_POINTER;
1016
   }
1017
   *key = nullptr;
1✔
1018
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1019
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(std::span{pubkey, 32});
1✔
1020
      return ffi_new_object(key, std::move(x25519));
1✔
1021
   });
2✔
1022
#else
1023
   BOTAN_UNUSED(key, pubkey);
1024
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1025
#endif
1026
}
1027

1028
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
1029
   if(output == nullptr) {
1✔
1030
      return BOTAN_FFI_ERROR_NULL_POINTER;
1031
   }
1032
#if defined(BOTAN_HAS_X25519)
1033
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
1034
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
1035
         const auto x25519_key = x25519->raw_private_key_bits();
1036
         if(x25519_key.size() != 32) {
1037
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
1038
         }
1039
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
1040
         return BOTAN_FFI_SUCCESS;
1041
      } else {
1042
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1043
      }
1044
   });
1045
#else
1046
   BOTAN_UNUSED(key, output);
1047
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1048
#endif
1049
}
1050

1051
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
1052
   if(output == nullptr) {
2✔
1053
      return BOTAN_FFI_ERROR_NULL_POINTER;
1054
   }
1055
#if defined(BOTAN_HAS_X25519)
1056
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
6✔
1057
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
1058
         Botan::copy_mem(std::span{output, 32}, x25519->raw_public_key_bits());
1059
         return BOTAN_FFI_SUCCESS;
1060
      } else {
1061
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1062
      }
1063
   });
1064
#else
1065
   BOTAN_UNUSED(key, output);
1066
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1067
#endif
1068
}
1069

1070
/* X448 specific operations */
1071

1072
int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
1✔
1073
#if defined(BOTAN_HAS_X448)
1074
   if(key == nullptr) {
1✔
1075
      return BOTAN_FFI_ERROR_NULL_POINTER;
1076
   }
1077
   *key = nullptr;
1✔
1078
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1079
      auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span{privkey, 56});
1✔
1080
      return ffi_new_object(key, std::move(x448));
2✔
1081
   });
2✔
1082
#else
1083
   BOTAN_UNUSED(key, privkey);
1084
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1085
#endif
1086
}
1087

1088
int botan_pubkey_load_x448(botan_pubkey_t* key, const uint8_t pubkey[56]) {
1✔
1089
#if defined(BOTAN_HAS_X448)
1090
   if(key == nullptr) {
1✔
1091
      return BOTAN_FFI_ERROR_NULL_POINTER;
1092
   }
1093
   *key = nullptr;
1✔
1094
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1095
      auto x448 = std::make_unique<Botan::X448_PublicKey>(std::span{pubkey, 56});
1✔
1096
      return ffi_new_object(key, std::move(x448));
1✔
1097
   });
2✔
1098
#else
1099
   BOTAN_UNUSED(key, pubkey);
1100
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1101
#endif
1102
}
1103

1104
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56]) {
1✔
1105
   if(output == nullptr) {
1✔
1106
      return BOTAN_FFI_ERROR_NULL_POINTER;
1107
   }
1108
#if defined(BOTAN_HAS_X448)
1109
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
1110
      if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
1111
         const auto x448_key = x448->raw_private_key_bits();
1112
         Botan::copy_mem(std::span{output, 56}, x448_key);
1113
         return BOTAN_FFI_SUCCESS;
1114
      } else {
1115
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1116
      }
1117
   });
1118
#else
1119
   BOTAN_UNUSED(key, output);
1120
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1121
#endif
1122
}
1123

1124
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
2✔
1125
   if(output == nullptr) {
2✔
1126
      return BOTAN_FFI_ERROR_NULL_POINTER;
1127
   }
1128
#if defined(BOTAN_HAS_X448)
1129
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
6✔
1130
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
1131
         Botan::copy_mem(std::span{output, 56}, x448->raw_public_key_bits());
1132
         return BOTAN_FFI_SUCCESS;
1133
      } else {
1134
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1135
      }
1136
   });
1137
#else
1138
   BOTAN_UNUSED(key, output);
1139
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1140
#endif
1141
}
1142

1143
/*
1144
* Algorithm specific key operations: Kyber
1145
*/
1146

1147
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
1148
#if defined(BOTAN_HAS_KYBER)
1149
   if(Botan::any_null_pointers(key, privkey)) {
4✔
1150
      return BOTAN_FFI_ERROR_NULL_POINTER;
1151
   }
1152
   *key = nullptr;
4✔
1153

1154
   const auto mode = [](size_t len) -> std::optional<Botan::KyberMode> {
12✔
1155
      if(len == 1632) {
4✔
1156
         return Botan::KyberMode::Kyber512_R3;
1✔
1157
      } else if(len == 2400) {
3✔
1158
         return Botan::KyberMode::Kyber768_R3;
2✔
1159
      } else if(len == 3168) {
1✔
1160
         return Botan::KyberMode::Kyber1024_R3;
1✔
1161
      } else {
1162
         return {};
×
1163
      }
1164
   }(key_len);
4✔
1165

1166
   if(mode.has_value()) {
4✔
1167
      return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1168
         auto kyber = std::make_unique<Botan::Kyber_PrivateKey>(std::span{privkey, key_len}, *mode);
4✔
1169
         return ffi_new_object(key, std::move(kyber));
8✔
1170
      });
4✔
1171
   } else {
1172
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
1173
   }
1174
#else
1175
   BOTAN_UNUSED(key, key_len, privkey);
1176
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1177
#endif
1178
}
1179

1180
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
1181
#if defined(BOTAN_HAS_KYBER)
1182
   if(Botan::any_null_pointers(key, pubkey)) {
4✔
1183
      return BOTAN_FFI_ERROR_NULL_POINTER;
1184
   }
1185
   *key = nullptr;
4✔
1186

1187
   const auto mode = [](size_t len) -> std::optional<Botan::KyberMode> {
12✔
1188
      if(len == 800) {
4✔
1189
         return Botan::KyberMode::Kyber512_R3;
1✔
1190
      } else if(len == 1184) {
3✔
1191
         return Botan::KyberMode::Kyber768_R3;
2✔
1192
      } else if(len == 1568) {
1✔
1193
         return Botan::KyberMode::Kyber1024_R3;
1✔
1194
      } else {
1195
         return {};
×
1196
      }
1197
   }(key_len);
4✔
1198

1199
   if(mode.has_value()) {
4✔
1200
      return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1201
         auto kyber = std::make_unique<Botan::Kyber_PublicKey>(std::span{pubkey, key_len}, *mode);
4✔
1202
         return ffi_new_object(key, std::move(kyber));
4✔
1203
      });
4✔
1204
   } else {
1205
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
1206
   }
1207
#else
1208
   BOTAN_UNUSED(key, pubkey, key_len);
1209
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1210
#endif
1211
}
1212

1213
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1214
#if defined(BOTAN_HAS_KYBER)
1215
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
16✔
1216
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1217
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1218
      } else {
1219
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1220
      }
1221
   });
1222
#else
1223
   BOTAN_UNUSED(key, ctx, view);
1224
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1225
#endif
1226
}
1227

1228
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1229
#if defined(BOTAN_HAS_KYBER)
1230
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
32✔
1231
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1232
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1233
      } else {
1234
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1235
      }
1236
   });
1237
#else
1238
   BOTAN_UNUSED(key, ctx, view);
1239
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1240
#endif
1241
}
1242

1243
/*
1244
* Algorithm specific key operations: ML-KEM
1245
*/
1246

1247
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1248
#if defined(BOTAN_HAS_ML_KEM)
1249
   if(Botan::any_null_pointers(key, privkey, mlkem_mode)) {
4✔
1250
      return BOTAN_FFI_ERROR_NULL_POINTER;
1251
   }
1252

1253
   *key = nullptr;
4✔
1254

1255
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1256
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1257
      if(!mode.is_ml_kem()) {
4✔
1258
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1259
      }
1260

1261
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1262
      return ffi_new_object(key, std::move(mlkem_key));
4✔
1263
   });
8✔
1264
#else
1265
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1266
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1267
#endif
1268
}
1269

1270
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
4✔
1271
#if defined(BOTAN_HAS_ML_KEM)
1272
   if(Botan::any_null_pointers(key, pubkey, mlkem_mode)) {
4✔
1273
      return BOTAN_FFI_ERROR_NULL_POINTER;
1274
   }
1275

1276
   *key = nullptr;
4✔
1277

1278
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1279
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1280
      if(!mode.is_ml_kem()) {
4✔
1281
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1282
      }
1283

1284
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PublicKey>(std::span{pubkey, key_len}, mode.mode());
4✔
1285
      return ffi_new_object(key, std::move(mlkem_key));
4✔
1286
   });
8✔
1287
#else
1288
   BOTAN_UNUSED(key, key_len, pubkey, mlkem_mode);
1289
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1290
#endif
1291
}
1292

1293
/*
1294
* Algorithm specific key operations: ML-DSA
1295
*/
1296

1297
int botan_privkey_load_ml_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mldsa_mode) {
4✔
1298
#if defined(BOTAN_HAS_ML_DSA)
1299
   if(Botan::any_null_pointers(key, privkey, mldsa_mode)) {
4✔
1300
      return BOTAN_FFI_ERROR_NULL_POINTER;
1301
   }
1302

1303
   *key = nullptr;
4✔
1304

1305
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1306
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1307
      if(!mode.is_ml_dsa()) {
4✔
1308
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1309
      }
1310

1311
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1312
      return ffi_new_object(key, std::move(mldsa_key));
4✔
1313
   });
8✔
1314
#else
1315
   BOTAN_UNUSED(key, key_len, privkey, mldsa_mode);
1316
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1317
#endif
1318
}
1319

1320
int botan_pubkey_load_ml_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mldsa_mode) {
4✔
1321
#if defined(BOTAN_HAS_ML_DSA)
1322
   if(Botan::any_null_pointers(key, pubkey, mldsa_mode)) {
4✔
1323
      return BOTAN_FFI_ERROR_NULL_POINTER;
1324
   }
1325

1326
   *key = nullptr;
4✔
1327

1328
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1329
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1330
      if(!mode.is_ml_dsa()) {
4✔
1331
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1332
      }
1333

1334
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
4✔
1335
      return ffi_new_object(key, std::move(mldsa_key));
4✔
1336
   });
8✔
1337
#else
1338
   BOTAN_UNUSED(key, key_len, pubkey, mldsa_mode);
1339
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1340
#endif
1341
}
1342

1343
/*
1344
* Algorithm specific key operations: SLH-DSA
1345
*/
1346

1347
int botan_privkey_load_slh_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1348
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1349
   if(Botan::any_null_pointers(key, privkey, slhdsa_mode)) {
13✔
1350
      return BOTAN_FFI_ERROR_NULL_POINTER;
1351
   }
1352

1353
   *key = nullptr;
13✔
1354

1355
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1356
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1357
      if(!mode.is_slh_dsa()) {
13✔
1358
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1359
      }
1360

1361
      auto slhdsa_key = std::make_unique<Botan::SLH_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1362
      return ffi_new_object(key, std::move(slhdsa_key));
13✔
1363
   });
26✔
1364
#else
1365
   BOTAN_UNUSED(key, key_len, privkey, slhdsa_mode);
1366
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1367
#endif
1368
}
1369

1370
int botan_pubkey_load_slh_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1371
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1372
   if(Botan::any_null_pointers(key, pubkey, slhdsa_mode)) {
13✔
1373
      return BOTAN_FFI_ERROR_NULL_POINTER;
1374
   }
1375

1376
   *key = nullptr;
13✔
1377

1378
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1379
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1380
      if(!mode.is_slh_dsa()) {
13✔
1381
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1382
      }
1383

1384
      auto mldsa_key = std::make_unique<Botan::SLH_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1385
      return ffi_new_object(key, std::move(mldsa_key));
13✔
1386
   });
26✔
1387
#else
1388
   BOTAN_UNUSED(key, key_len, pubkey, slhdsa_mode);
1389
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1390
#endif
1391
}
1392

1393
/*
1394
* Algorithm specific key operations: FrodoKEM
1395
*/
1396

1397
int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* frodo_mode) {
13✔
1398
#if defined(BOTAN_HAS_FRODOKEM)
1399
   if(Botan::any_null_pointers(key, privkey, frodo_mode)) {
13✔
1400
      return BOTAN_FFI_ERROR_NULL_POINTER;
1401
   }
1402

1403
   *key = nullptr;
13✔
1404

1405
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1406
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1407
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1408
      return ffi_new_object(key, std::move(frodo_key));
26✔
1409
   });
26✔
1410
#else
1411
   BOTAN_UNUSED(key, privkey, key_len, frodo_mode);
1412
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1413
#endif
1414
}
1415

1416
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode) {
13✔
1417
#if defined(BOTAN_HAS_FRODOKEM)
1418
   if(Botan::any_null_pointers(key, pubkey, frodo_mode)) {
13✔
1419
      return BOTAN_FFI_ERROR_NULL_POINTER;
1420
   }
1421

1422
   *key = nullptr;
13✔
1423

1424
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1425
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1426
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1427
      return ffi_new_object(key, std::move(frodo_key));
13✔
1428
   });
26✔
1429
#else
1430
   BOTAN_UNUSED(key, pubkey, key_len, frodo_mode);
1431
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1432
#endif
1433
}
1434

1435
/*
1436
* Algorithm specific key operations : Classic McEliece
1437
*/
1438

1439
int botan_privkey_load_classic_mceliece(botan_privkey_t* key,
17✔
1440
                                        const uint8_t privkey[],
1441
                                        size_t key_len,
1442
                                        const char* cmce_mode) {
1443
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1444
   if(Botan::any_null_pointers(key, privkey, cmce_mode)) {
17✔
1445
      return BOTAN_FFI_ERROR_NULL_POINTER;
1446
   }
1447

1448
   *key = nullptr;
17✔
1449

1450
   return ffi_guard_thunk(__func__, [=]() -> int {
17✔
1451
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1452
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PrivateKey>(std::span{privkey, key_len}, mode);
17✔
1453
      return ffi_new_object(key, std::move(cmce_key));
34✔
1454
   });
34✔
1455
#else
1456
   BOTAN_UNUSED(key, privkey, key_len, cmce_mode);
1457
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1458
#endif
1459
}
1460

1461
int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
17✔
1462
                                       const uint8_t pubkey[],
1463
                                       size_t key_len,
1464
                                       const char* cmce_mode) {
1465
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1466
   if(Botan::any_null_pointers(key, pubkey, cmce_mode)) {
17✔
1467
      return BOTAN_FFI_ERROR_NULL_POINTER;
1468
   }
1469

1470
   *key = nullptr;
17✔
1471

1472
   return ffi_guard_thunk(__func__, [=]() -> int {
17✔
1473
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1474
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PublicKey>(std::span{pubkey, key_len}, mode);
17✔
1475
      return ffi_new_object(key, std::move(cmce_key));
17✔
1476
   });
34✔
1477
#else
1478
   BOTAN_UNUSED(key, pubkey, key_len, cmce_mode);
1479
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1480
#endif
1481
}
1482

1483
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1484
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1485
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1486
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1487
         auto pt = ecc->_public_ec_point().serialize_uncompressed();
1488
         return invoke_view_callback(view, ctx, pt);
1489
      } else {
1490
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1491
      }
1492
   });
1493
#else
1494
   BOTAN_UNUSED(key, view, ctx);
1495
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1496
#endif
1497
}
1498

1499
// NOLINTEND(misc-misplaced-const)
1500

1501
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1502
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1503
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1504
}
1✔
1505

1506
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1507
                         const char* aead,
1508
                         const uint8_t ct[],
1509
                         size_t ct_len,
1510
                         const uint8_t ad[],
1511
                         size_t ad_len,
1512
                         uint8_t out[],
1513
                         size_t* out_len) {
1514
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1515
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1516
}
1517

1518
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1519
                         botan_rng_t rng_obj,
1520
                         const char* aead,
1521
                         const uint8_t pt[],
1522
                         size_t pt_len,
1523
                         const uint8_t ad[],
1524
                         size_t ad_len,
1525
                         uint8_t out[],
1526
                         size_t* out_len) {
1527
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1528
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1529
}
1530
}
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