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

randombit / botan / 21753596263

06 Feb 2026 02:13PM UTC coverage: 90.063% (-0.01%) from 90.073%
21753596263

Pull #5289

github

web-flow
Merge 587099284 into 8ea0ca252
Pull Request #5289: Further misc header reductions, forward declarations, etc

102237 of 113517 relevant lines covered (90.06%)

11402137.11 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/ec_group.h>
12
#include <botan/hash.h>
13
#include <botan/pem.h>
14
#include <botan/internal/ffi_mp.h>
15
#include <botan/internal/ffi_pkey.h>
16
#include <botan/internal/ffi_rng.h>
17
#include <botan/internal/ffi_util.h>
18

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

99
namespace {
100

101
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
102

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

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

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

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

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

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

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

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

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

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

161
#endif
162

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

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

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

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

201
}  // namespace
202

203
extern "C" {
204

205
using namespace Botan_FFI;
206

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

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

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

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

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

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

227
/* RSA specific operations */
228

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

444
/* ECDSA specific operations */
445

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

597
/* Diffie Hellman specific operations */
598

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

725
/* SM2 specific operations */
726

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

840
/* Ed25519 specific operations */
841

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

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

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

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

916
/* Ed448 specific operations */
917

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

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

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

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

984
/* X25519 specific operations */
985

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

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

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

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

1054
/* X448 specific operations */
1055

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

1072
int botan_pubkey_load_x448(botan_pubkey_t* key, const uint8_t pubkey[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_PublicKey>(std::span{pubkey, 56});
1✔
1080
      return ffi_new_object(key, std::move(x448));
1✔
1081
   });
2✔
1082
#else
1083
   BOTAN_UNUSED(key, pubkey);
1084
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1085
#endif
1086
}
1087

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

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

1121
/*
1122
* Algorithm specific key operations: Kyber
1123
*/
1124

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

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

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

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

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

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

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

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

1219
/*
1220
* Algorithm specific key operations: ML-KEM
1221
*/
1222

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

1229
   *key = nullptr;
4✔
1230

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

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

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

1252
   *key = nullptr;
4✔
1253

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

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

1269
/*
1270
* Algorithm specific key operations: ML-DSA
1271
*/
1272

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

1279
   *key = nullptr;
4✔
1280

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

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

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

1302
   *key = nullptr;
4✔
1303

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

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

1319
/*
1320
* Algorithm specific key operations: SLH-DSA
1321
*/
1322

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

1329
   *key = nullptr;
13✔
1330

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

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

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

1352
   *key = nullptr;
13✔
1353

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

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

1369
/*
1370
* Algorithm specific key operations: FrodoKEM
1371
*/
1372

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

1379
   *key = nullptr;
13✔
1380

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

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

1398
   *key = nullptr;
13✔
1399

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

1411
/*
1412
* Algorithm specific key operations : Classic McEliece
1413
*/
1414

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

1424
   *key = nullptr;
17✔
1425

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

1437
int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
17✔
1438
                                       const uint8_t pubkey[],
1439
                                       size_t key_len,
1440
                                       const char* cmce_mode) {
1441
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1442
   if(key == nullptr || pubkey == nullptr || cmce_mode == nullptr) {
17✔
1443
      return BOTAN_FFI_ERROR_NULL_POINTER;
1444
   }
1445

1446
   *key = nullptr;
17✔
1447

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

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

1475
// NOLINTEND(misc-misplaced-const)
1476

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

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

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