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

randombit / botan / 21972093278

13 Feb 2026 02:16AM UTC coverage: 90.067%. Remained the same
21972093278

Pull #5321

github

web-flow
Merge a72b55147 into e7443105f
Pull Request #5321: Avoid various unneeded include files

102230 of 113505 relevant lines covered (90.07%)

11457215.35 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_DIFFIE_HELLMAN)
70
   #include <botan/dh.h>
71
#endif
72

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

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

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

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

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

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

97
namespace {
98

99
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
100

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

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

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

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

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

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

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

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

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

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

159
#endif
160

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

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

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

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

199
}  // namespace
200

201
extern "C" {
202

203
using namespace Botan_FFI;
204

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

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

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

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

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

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

225
/* RSA specific operations */
226

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

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

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

237
int botan_privkey_load_rsa(botan_privkey_t* key, botan_mp_t rsa_p, botan_mp_t rsa_q, botan_mp_t rsa_e) {
2✔
238
#if defined(BOTAN_HAS_RSA)
239
   if(key == nullptr) {
2✔
240
      return BOTAN_FFI_ERROR_NULL_POINTER;
241
   }
242
   *key = nullptr;
2✔
243

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

382
int botan_privkey_load_dsa(botan_privkey_t* key, botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t x) {
2✔
383
#if defined(BOTAN_HAS_DSA)
384
   if(key == nullptr) {
2✔
385
      return BOTAN_FFI_ERROR_NULL_POINTER;
386
   }
387
   *key = nullptr;
2✔
388

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

400
int botan_pubkey_load_dsa(botan_pubkey_t* key, botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t y) {
2✔
401
#if defined(BOTAN_HAS_DSA)
402
   if(key == nullptr) {
2✔
403
      return BOTAN_FFI_ERROR_NULL_POINTER;
404
   }
405
   *key = nullptr;
2✔
406

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

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

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

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

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

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

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

442
/* ECDSA specific operations */
443

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

595
/* Diffie Hellman specific operations */
596

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

723
/* SM2 specific operations */
724

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

838
/* Ed25519 specific operations */
839

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

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

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

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

914
/* Ed448 specific operations */
915

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

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

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

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

982
/* X25519 specific operations */
983

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

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

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

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

1052
/* X448 specific operations */
1053

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

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

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

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

1119
/*
1120
* Algorithm specific key operations: Kyber
1121
*/
1122

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

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

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

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

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

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

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

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

1217
/*
1218
* Algorithm specific key operations: ML-KEM
1219
*/
1220

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

1227
   *key = nullptr;
4✔
1228

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

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

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

1250
   *key = nullptr;
4✔
1251

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

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

1267
/*
1268
* Algorithm specific key operations: ML-DSA
1269
*/
1270

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

1277
   *key = nullptr;
4✔
1278

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

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

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

1300
   *key = nullptr;
4✔
1301

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

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

1317
/*
1318
* Algorithm specific key operations: SLH-DSA
1319
*/
1320

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

1327
   *key = nullptr;
13✔
1328

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

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

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

1350
   *key = nullptr;
13✔
1351

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

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

1367
/*
1368
* Algorithm specific key operations: FrodoKEM
1369
*/
1370

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

1377
   *key = nullptr;
13✔
1378

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

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

1396
   *key = nullptr;
13✔
1397

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

1409
/*
1410
* Algorithm specific key operations : Classic McEliece
1411
*/
1412

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

1422
   *key = nullptr;
17✔
1423

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

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

1444
   *key = nullptr;
17✔
1445

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

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

1473
// NOLINTEND(misc-misplaced-const)
1474

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

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

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