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

randombit / botan / 21892189369

11 Feb 2026 12:53AM UTC coverage: 90.069% (-1.6%) from 91.638%
21892189369

push

github

web-flow
Merge pull request #5302 from randombit/jack/header-patrol-4

Cleanup various header inclusions

102230 of 113502 relevant lines covered (90.07%)

11577018.64 hits per line

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

96.53
/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_MCELIECE)
70
   #include <botan/mceliece.h>
71
#endif
72

73
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
74
   #include <botan/dh.h>
75
#endif
76

77
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
78
   #include <botan/kyber.h>
79
#endif
80

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

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

89
#if defined(BOTAN_HAS_ML_DSA)
90
   #include <botan/ml_dsa.h>
91
#endif
92

93
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
94
   #include <botan/slh_dsa.h>
95
#endif
96

97
#if defined(BOTAN_HAS_CLASSICMCELIECE)
98
   #include <botan/cmce.h>
99
#endif
100

101
namespace {
102

103
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
104

105
// These are always called within an existing try/catch block
106

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

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

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

131
   if(!Botan::EC_Group::supports_named_group(curve_name)) {
6✔
132
      return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
133
   }
134

135
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
136

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

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

153
   const auto group = Botan::EC_Group::from_name(curve_name);
14✔
154

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

163
#endif
164

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

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

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

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

203
}  // namespace
204

205
extern "C" {
206

207
using namespace Botan_FFI;
208

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

214
   const std::string field_name(field_name_cstr);
40✔
215

216
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
217
}
40✔
218

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

224
   const std::string field_name(field_name_cstr);
35✔
225

226
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
136✔
227
}
35✔
228

229
/* RSA specific operations */
230

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

236
   const std::string n_str = std::to_string(n_bits);
2✔
237

238
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
2✔
239
}
2✔
240

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

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

258
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
259
#if defined(BOTAN_HAS_RSA)
260
   if(key == nullptr || bits == nullptr) {
1✔
261
      return BOTAN_FFI_ERROR_NULL_POINTER;
262
   }
263
   *key = nullptr;
1✔
264

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

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

292
int botan_pubkey_load_rsa_pkcs1(botan_pubkey_t* key, const uint8_t bits[], size_t len) {
×
293
#if defined(BOTAN_HAS_RSA)
294
   if(key == nullptr || bits == nullptr) {
×
295
      return BOTAN_FFI_ERROR_NULL_POINTER;
296
   }
297
   *key = nullptr;
×
298

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

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

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

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

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

326
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
1✔
327
   return botan_privkey_get_field(d, key, "d");
1✔
328
}
329

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

334
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
335
   return botan_pubkey_get_field(n, key, "n");
1✔
336
}
337

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

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

366
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
367
      return BOTAN_FFI_ERROR_NULL_POINTER;
368
   }
369

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

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

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

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

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

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

422
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
423
   return botan_privkey_get_field(x, key, "x");
2✔
424
}
425

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

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

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

438
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
439
   return botan_pubkey_get_field(y, key, "y");
2✔
440
}
441

442
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
443
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
444
}
445

446
/* ECDSA specific operations */
447

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

454
      if(ec_key == nullptr) {
9✔
455
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
456
      }
457

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

466
// NOLINTBEGIN(misc-misplaced-const)
467

468
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
469
                            const botan_mp_t public_x,
470
                            const botan_mp_t public_y,
471
                            const char* curve_name) {
472
#if defined(BOTAN_HAS_ECDSA)
473
   if(key == nullptr || curve_name == nullptr) {
2✔
474
      return BOTAN_FFI_ERROR_NULL_POINTER;
475
   }
476
   *key = nullptr;
2✔
477

478
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
479
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
480

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

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

494
int botan_pubkey_load_ecdsa_sec1(botan_pubkey_t* key, const uint8_t sec1[], size_t sec1_len, const char* curve_name) {
3✔
495
#if defined(BOTAN_HAS_ECDSA)
496
   if(key == nullptr || sec1 == nullptr || curve_name == nullptr) {
3✔
497
      return BOTAN_FFI_ERROR_NULL_POINTER;
498
   }
499
   *key = nullptr;
3✔
500

501
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
502
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
3✔
503

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

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

517
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
518
#if defined(BOTAN_HAS_ECDSA)
519
   if(key == nullptr || curve_name == nullptr) {
2✔
520
      return BOTAN_FFI_ERROR_NULL_POINTER;
521
   }
522
   *key = nullptr;
2✔
523

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

538
/* ElGamal specific operations */
539
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
540
#if defined(BOTAN_HAS_ELGAMAL)
541
   if(key == nullptr || rng_obj == nullptr) {
1✔
542
      return BOTAN_FFI_ERROR_NULL_POINTER;
543
   }
544
   *key = nullptr;
1✔
545

546
   if(pbits < 1024 || qbits < 160) {
1✔
547
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
548
   }
549

550
   const Botan::DL_Group::PrimeType prime_type =
1✔
551
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
552

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

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

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

599
/* Diffie Hellman specific operations */
600

601
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
602
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
603
}
604

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

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

639
/* ECDH + x25519/x448 specific operations */
640

641
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
642
   if(key_obj == nullptr || param_str == nullptr) {
2✔
643
      return BOTAN_FFI_ERROR_NULL_POINTER;
644
   }
645
   *key_obj = nullptr;
2✔
646

647
   const std::string params(param_str);
2✔
648

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

653
   if(params == "X448" || params == "x448") {
2✔
654
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
655
   }
656

657
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
658
}
2✔
659

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

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

684
int botan_pubkey_load_ecdh_sec1(botan_pubkey_t* key, const uint8_t sec1[], size_t sec1_len, const char* curve_name) {
7✔
685
#if defined(BOTAN_HAS_ECDH)
686
   if(key == nullptr || sec1 == nullptr || curve_name == nullptr) {
7✔
687
      return BOTAN_FFI_ERROR_NULL_POINTER;
688
   }
689
   *key = nullptr;
7✔
690

691
   return ffi_guard_thunk(__func__, [=]() -> int {
7✔
692
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
7✔
693

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

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

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

727
/* SM2 specific operations */
728

729
int botan_pubkey_sm2_compute_za(
2✔
730
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
731
   if(out == nullptr || out_len == nullptr || ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
732
      return BOTAN_FFI_ERROR_NULL_POINTER;
733
   }
734

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

740
      if(ec_key == nullptr) {
2✔
741
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
742
      }
743

744
      if(ec_key->algo_name() != "SM2") {
2✔
745
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
746
      }
747

748
      const std::string ident_str(ident);
2✔
749
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
750

751
      const auto& pt = ec_key->_public_ec_point();
2✔
752

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

755
      return write_vec_output(out, out_len, za);
2✔
756
   });
6✔
757
#else
758
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
759
#endif
760
}
761

762
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
763
                          const botan_mp_t public_x,
764
                          const botan_mp_t public_y,
765
                          const char* curve_name) {
766
#if defined(BOTAN_HAS_SM2)
767
   if(key == nullptr || curve_name == nullptr) {
3✔
768
      return BOTAN_FFI_ERROR_NULL_POINTER;
769
   }
770
   *key = nullptr;
3✔
771

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

786
int botan_pubkey_load_sm2_sec1(botan_pubkey_t* key, const uint8_t sec1[], size_t sec1_len, const char* curve_name) {
4✔
787
#if defined(BOTAN_HAS_SM2)
788
   if(key == nullptr || sec1 == nullptr || curve_name == nullptr) {
4✔
789
      return BOTAN_FFI_ERROR_NULL_POINTER;
790
   }
791
   *key = nullptr;
4✔
792

793
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
794
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
4✔
795

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

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

809
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
810
#if defined(BOTAN_HAS_SM2)
811
   if(key == nullptr || curve_name == nullptr) {
3✔
812
      return BOTAN_FFI_ERROR_NULL_POINTER;
813
   }
814
   *key = nullptr;
3✔
815

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

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

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

838
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
839
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
840
}
841

842
/* Ed25519 specific operations */
843

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

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

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

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

918
/* Ed448 specific operations */
919

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

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

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

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

986
/* X25519 specific operations */
987

988
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
989
#if defined(BOTAN_HAS_X25519)
990
   if(key == nullptr) {
1✔
991
      return BOTAN_FFI_ERROR_NULL_POINTER;
992
   }
993
   *key = nullptr;
1✔
994
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
995
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(std::span{privkey, 32});
1✔
996
      return ffi_new_object(key, std::move(x25519));
2✔
997
   });
2✔
998
#else
999
   BOTAN_UNUSED(key, privkey);
1000
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1001
#endif
1002
}
1003

1004
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
1005
#if defined(BOTAN_HAS_X25519)
1006
   if(key == nullptr) {
1✔
1007
      return BOTAN_FFI_ERROR_NULL_POINTER;
1008
   }
1009
   *key = nullptr;
1✔
1010
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1011
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(std::span{pubkey, 32});
1✔
1012
      return ffi_new_object(key, std::move(x25519));
1✔
1013
   });
2✔
1014
#else
1015
   BOTAN_UNUSED(key, pubkey);
1016
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1017
#endif
1018
}
1019

1020
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
1021
#if defined(BOTAN_HAS_X25519)
1022
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
1023
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
1024
         const auto x25519_key = x25519->raw_private_key_bits();
1025
         if(x25519_key.size() != 32) {
1026
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
1027
         }
1028
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
1029
         return BOTAN_FFI_SUCCESS;
1030
      } else {
1031
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1032
      }
1033
   });
1034
#else
1035
   BOTAN_UNUSED(key, output);
1036
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1037
#endif
1038
}
1039

1040
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
1041
#if defined(BOTAN_HAS_X25519)
1042
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
6✔
1043
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
1044
         Botan::copy_mem(std::span{output, 32}, x25519->raw_public_key_bits());
1045
         return BOTAN_FFI_SUCCESS;
1046
      } else {
1047
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1048
      }
1049
   });
1050
#else
1051
   BOTAN_UNUSED(key, output);
1052
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1053
#endif
1054
}
1055

1056
/* X448 specific operations */
1057

1058
int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
1✔
1059
#if defined(BOTAN_HAS_X448)
1060
   if(key == nullptr) {
1✔
1061
      return BOTAN_FFI_ERROR_NULL_POINTER;
1062
   }
1063
   *key = nullptr;
1✔
1064
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1065
      auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span{privkey, 56});
1✔
1066
      return ffi_new_object(key, std::move(x448));
2✔
1067
   });
2✔
1068
#else
1069
   BOTAN_UNUSED(key, privkey);
1070
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1071
#endif
1072
}
1073

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

1090
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56]) {
1✔
1091
#if defined(BOTAN_HAS_X448)
1092
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
1093
      if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
1094
         const auto x448_key = x448->raw_private_key_bits();
1095
         Botan::copy_mem(std::span{output, 56}, x448_key);
1096
         return BOTAN_FFI_SUCCESS;
1097
      } else {
1098
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1099
      }
1100
   });
1101
#else
1102
   BOTAN_UNUSED(key, output);
1103
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1104
#endif
1105
}
1106

1107
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
2✔
1108
#if defined(BOTAN_HAS_X448)
1109
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
6✔
1110
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
1111
         Botan::copy_mem(std::span{output, 56}, x448->raw_public_key_bits());
1112
         return BOTAN_FFI_SUCCESS;
1113
      } else {
1114
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1115
      }
1116
   });
1117
#else
1118
   BOTAN_UNUSED(key, output);
1119
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1120
#endif
1121
}
1122

1123
/*
1124
* Algorithm specific key operations: Kyber
1125
*/
1126

1127
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
1128
#if defined(BOTAN_HAS_KYBER)
1129
   if(key == nullptr) {
4✔
1130
      return BOTAN_FFI_ERROR_NULL_POINTER;
1131
   }
1132
   *key = nullptr;
4✔
1133

1134
   const auto mode = [](size_t len) -> std::optional<Botan::KyberMode> {
12✔
1135
      if(len == 1632) {
4✔
1136
         return Botan::KyberMode::Kyber512_R3;
1✔
1137
      } else if(len == 2400) {
3✔
1138
         return Botan::KyberMode::Kyber768_R3;
2✔
1139
      } else if(len == 3168) {
1✔
1140
         return Botan::KyberMode::Kyber1024_R3;
1✔
1141
      } else {
1142
         return {};
×
1143
      }
1144
   }(key_len);
4✔
1145

1146
   if(mode.has_value()) {
4✔
1147
      return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1148
         auto kyber = std::make_unique<Botan::Kyber_PrivateKey>(std::span{privkey, key_len}, *mode);
4✔
1149
         return ffi_new_object(key, std::move(kyber));
8✔
1150
      });
4✔
1151
   } else {
1152
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
1153
   }
1154
#else
1155
   BOTAN_UNUSED(key, key_len, privkey);
1156
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1157
#endif
1158
}
1159

1160
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
1161
#if defined(BOTAN_HAS_KYBER)
1162
   if(key == nullptr) {
4✔
1163
      return BOTAN_FFI_ERROR_NULL_POINTER;
1164
   }
1165
   *key = nullptr;
4✔
1166

1167
   const auto mode = [](size_t len) -> std::optional<Botan::KyberMode> {
12✔
1168
      if(len == 800) {
4✔
1169
         return Botan::KyberMode::Kyber512_R3;
1✔
1170
      } else if(len == 1184) {
3✔
1171
         return Botan::KyberMode::Kyber768_R3;
2✔
1172
      } else if(len == 1568) {
1✔
1173
         return Botan::KyberMode::Kyber1024_R3;
1✔
1174
      } else {
1175
         return {};
×
1176
      }
1177
   }(key_len);
4✔
1178

1179
   if(mode.has_value()) {
4✔
1180
      auto kyber = std::make_unique<Botan::Kyber_PublicKey>(std::span{pubkey, key_len}, *mode);
4✔
1181
      return ffi_new_object(key, std::move(kyber));
4✔
1182
   } else {
4✔
1183
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
1184
   }
1185
#else
1186
   BOTAN_UNUSED(key, pubkey, key_len);
1187
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1188
#endif
1189
}
1190

1191
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1192
#if defined(BOTAN_HAS_KYBER)
1193
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
16✔
1194
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1195
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1196
      } else {
1197
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1198
      }
1199
   });
1200
#else
1201
   BOTAN_UNUSED(key, ctx, view);
1202
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1203
#endif
1204
}
1205

1206
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1207
#if defined(BOTAN_HAS_KYBER)
1208
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
32✔
1209
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1210
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1211
      } else {
1212
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1213
      }
1214
   });
1215
#else
1216
   BOTAN_UNUSED(key, ctx, view);
1217
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1218
#endif
1219
}
1220

1221
/*
1222
* Algorithm specific key operations: ML-KEM
1223
*/
1224

1225
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1226
#if defined(BOTAN_HAS_ML_KEM)
1227
   if(key == nullptr || privkey == nullptr || mlkem_mode == nullptr) {
4✔
1228
      return BOTAN_FFI_ERROR_NULL_POINTER;
1229
   }
1230

1231
   *key = nullptr;
4✔
1232

1233
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1234
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1235
      if(!mode.is_ml_kem()) {
4✔
1236
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1237
      }
1238

1239
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1240
      return ffi_new_object(key, std::move(mlkem_key));
4✔
1241
   });
8✔
1242
#else
1243
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1244
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1245
#endif
1246
}
1247

1248
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
4✔
1249
#if defined(BOTAN_HAS_ML_KEM)
1250
   if(key == nullptr || pubkey == nullptr || mlkem_mode == nullptr) {
4✔
1251
      return BOTAN_FFI_ERROR_NULL_POINTER;
1252
   }
1253

1254
   *key = nullptr;
4✔
1255

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

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

1271
/*
1272
* Algorithm specific key operations: ML-DSA
1273
*/
1274

1275
int botan_privkey_load_ml_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mldsa_mode) {
4✔
1276
#if defined(BOTAN_HAS_ML_DSA)
1277
   if(key == nullptr || privkey == nullptr || mldsa_mode == nullptr) {
4✔
1278
      return BOTAN_FFI_ERROR_NULL_POINTER;
1279
   }
1280

1281
   *key = nullptr;
4✔
1282

1283
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1284
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1285
      if(!mode.is_ml_dsa()) {
4✔
1286
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1287
      }
1288

1289
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1290
      return ffi_new_object(key, std::move(mldsa_key));
4✔
1291
   });
8✔
1292
#else
1293
   BOTAN_UNUSED(key, key_len, privkey, mldsa_mode);
1294
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1295
#endif
1296
}
1297

1298
int botan_pubkey_load_ml_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mldsa_mode) {
4✔
1299
#if defined(BOTAN_HAS_ML_DSA)
1300
   if(key == nullptr || pubkey == nullptr || mldsa_mode == nullptr) {
4✔
1301
      return BOTAN_FFI_ERROR_NULL_POINTER;
1302
   }
1303

1304
   *key = nullptr;
4✔
1305

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

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

1321
/*
1322
* Algorithm specific key operations: SLH-DSA
1323
*/
1324

1325
int botan_privkey_load_slh_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1326
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1327
   if(key == nullptr || privkey == nullptr || slhdsa_mode == nullptr) {
13✔
1328
      return BOTAN_FFI_ERROR_NULL_POINTER;
1329
   }
1330

1331
   *key = nullptr;
13✔
1332

1333
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1334
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1335
      if(!mode.is_slh_dsa()) {
13✔
1336
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1337
      }
1338

1339
      auto slhdsa_key = std::make_unique<Botan::SLH_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1340
      return ffi_new_object(key, std::move(slhdsa_key));
13✔
1341
   });
26✔
1342
#else
1343
   BOTAN_UNUSED(key, key_len, privkey, slhdsa_mode);
1344
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1345
#endif
1346
}
1347

1348
int botan_pubkey_load_slh_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1349
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1350
   if(key == nullptr || pubkey == nullptr || slhdsa_mode == nullptr) {
13✔
1351
      return BOTAN_FFI_ERROR_NULL_POINTER;
1352
   }
1353

1354
   *key = nullptr;
13✔
1355

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

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

1371
/*
1372
* Algorithm specific key operations: FrodoKEM
1373
*/
1374

1375
int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* frodo_mode) {
13✔
1376
#if defined(BOTAN_HAS_FRODOKEM)
1377
   if(key == nullptr || privkey == nullptr || frodo_mode == nullptr) {
13✔
1378
      return BOTAN_FFI_ERROR_NULL_POINTER;
1379
   }
1380

1381
   *key = nullptr;
13✔
1382

1383
   return ffi_guard_thunk(__func__, [=]() -> int {
13✔
1384
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1385
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1386
      return ffi_new_object(key, std::move(frodo_key));
26✔
1387
   });
26✔
1388
#else
1389
   BOTAN_UNUSED(key, privkey, key_len, frodo_mode);
1390
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1391
#endif
1392
}
1393

1394
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode) {
13✔
1395
#if defined(BOTAN_HAS_FRODOKEM)
1396
   if(key == nullptr || pubkey == nullptr || frodo_mode == nullptr) {
13✔
1397
      return BOTAN_FFI_ERROR_NULL_POINTER;
1398
   }
1399

1400
   *key = nullptr;
13✔
1401

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

1413
/*
1414
* Algorithm specific key operations : Classic McEliece
1415
*/
1416

1417
int botan_privkey_load_classic_mceliece(botan_privkey_t* key,
17✔
1418
                                        const uint8_t privkey[],
1419
                                        size_t key_len,
1420
                                        const char* cmce_mode) {
1421
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1422
   if(key == nullptr || privkey == nullptr || cmce_mode == nullptr) {
17✔
1423
      return BOTAN_FFI_ERROR_NULL_POINTER;
1424
   }
1425

1426
   *key = nullptr;
17✔
1427

1428
   return ffi_guard_thunk(__func__, [=]() -> int {
17✔
1429
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1430
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PrivateKey>(std::span{privkey, key_len}, mode);
17✔
1431
      return ffi_new_object(key, std::move(cmce_key));
34✔
1432
   });
34✔
1433
#else
1434
   BOTAN_UNUSED(key, privkey, key_len, cmce_mode);
1435
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1436
#endif
1437
}
1438

1439
int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
17✔
1440
                                       const uint8_t pubkey[],
1441
                                       size_t key_len,
1442
                                       const char* cmce_mode) {
1443
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1444
   if(key == nullptr || pubkey == nullptr || cmce_mode == nullptr) {
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_PublicKey>(std::span{pubkey, key_len}, mode);
17✔
1453
      return ffi_new_object(key, std::move(cmce_key));
17✔
1454
   });
34✔
1455
#else
1456
   BOTAN_UNUSED(key, pubkey, key_len, cmce_mode);
1457
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1458
#endif
1459
}
1460

1461
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1462
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1463
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1464
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1465
         auto pt = ecc->_public_ec_point().serialize_uncompressed();
1466
         return invoke_view_callback(view, ctx, pt);
1467
      } else {
1468
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1469
      }
1470
   });
1471
#else
1472
   BOTAN_UNUSED(key, view, ctx);
1473
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1474
#endif
1475
}
1476

1477
// NOLINTEND(misc-misplaced-const)
1478

1479
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1480
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1481
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1482
}
1✔
1483

1484
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1485
                         const char* aead,
1486
                         const uint8_t ct[],
1487
                         size_t ct_len,
1488
                         const uint8_t ad[],
1489
                         size_t ad_len,
1490
                         uint8_t out[],
1491
                         size_t* out_len) {
1492
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1493
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1494
}
1495

1496
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1497
                         botan_rng_t rng_obj,
1498
                         const char* aead,
1499
                         const uint8_t pt[],
1500
                         size_t pt_len,
1501
                         const uint8_t ad[],
1502
                         size_t ad_len,
1503
                         uint8_t out[],
1504
                         size_t* out_len) {
1505
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1506
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1507
}
1508
}
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