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

randombit / botan / 12661312886

07 Jan 2025 11:55PM UTC coverage: 91.251% (-0.02%) from 91.267%
12661312886

push

github

web-flow
Merge pull request #4518 from randombit/jack/ec-point-cleanups

Move EC_Point and related code to deprecated submodule

93407 of 102363 relevant lines covered (91.25%)

11518305.49 hits per line

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

98
namespace {
99

100
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
101

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

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

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

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

125
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
126

127
   if(auto pt = Botan::EC_AffinePoint::from_bigint_xy(group, public_x, public_y)) {
6✔
128
      key.reset(new ECPublicKey_t(group, pt.value()));
6✔
129
      return BOTAN_FFI_SUCCESS;
6✔
130
   } else {
131
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
132
   }
133
}
6✔
134

135
#endif
136

137
Botan::BigInt pubkey_get_field(const Botan::Public_Key& key, std::string_view field) {
40✔
138
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
139
   // Not currently handled by get_int_field
140
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
40✔
141
      if(field == "public_x") {
15✔
142
         return Botan::BigInt::from_bytes(ecc->_public_ec_point().x_bytes());
16✔
143
      } else if(field == "public_y") {
7✔
144
         return Botan::BigInt::from_bytes(ecc->_public_ec_point().y_bytes());
12✔
145
      }
146
   }
147
#endif
148

149
   try {
26✔
150
      return key.get_int_field(field);
26✔
151
   } catch(Botan::Unknown_PK_Field_Name&) {
2✔
152
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
2✔
153
   }
2✔
154
}
155

156
Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
35✔
157
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
158
   // Not currently handled by get_int_field
159
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
35✔
160
      if(field == "public_x") {
16✔
161
         return Botan::BigInt::from_bytes(ecc->_public_ec_point().x_bytes());
4✔
162
      } else if(field == "public_y") {
14✔
163
         return Botan::BigInt::from_bytes(ecc->_public_ec_point().y_bytes());
8✔
164
      }
165
   }
166
#endif
167

168
   try {
29✔
169
      return key.get_int_field(field);
29✔
170
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
171
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
172
   }
4✔
173
}
174

175
}  // namespace
176

177
extern "C" {
178

179
using namespace Botan_FFI;
180

181
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
182
   if(field_name_cstr == nullptr) {
40✔
183
      return BOTAN_FFI_ERROR_NULL_POINTER;
184
   }
185

186
   const std::string field_name(field_name_cstr);
40✔
187

188
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
189
}
40✔
190

191
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
192
   if(field_name_cstr == nullptr) {
35✔
193
      return BOTAN_FFI_ERROR_NULL_POINTER;
194
   }
195

196
   const std::string field_name(field_name_cstr);
35✔
197

198
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
140✔
199
}
35✔
200

201
/* RSA specific operations */
202

203
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
1✔
204
   if(n_bits < 1024 || n_bits > 16 * 1024) {
1✔
205
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
206
   }
207

208
   std::string n_str = std::to_string(n_bits);
1✔
209

210
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
211
}
1✔
212

213
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✔
214
#if defined(BOTAN_HAS_RSA)
215
   *key = nullptr;
2✔
216

217
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
218
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
2✔
219
      *key = new botan_privkey_struct(std::move(rsa));
2✔
220
      return BOTAN_FFI_SUCCESS;
2✔
221
   });
4✔
222
#else
223
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
224
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
225
#endif
226
}
227

228
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
229
#if defined(BOTAN_HAS_RSA)
230
   *key = nullptr;
1✔
231

232
   Botan::secure_vector<uint8_t> src(bits, bits + len);
1✔
233
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
234
      Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
1✔
235
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
1✔
236
      *key = new botan_privkey_struct(std::move(rsa));
1✔
237
      return BOTAN_FFI_SUCCESS;
1✔
238
   });
1✔
239
#else
240
   BOTAN_UNUSED(key, bits, len);
241
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
242
#endif
243
}
1✔
244

245
int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e) {
4✔
246
#if defined(BOTAN_HAS_RSA)
247
   *key = nullptr;
4✔
248
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
249
      auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
4✔
250
      *key = new botan_pubkey_struct(std::move(rsa));
6✔
251
      return BOTAN_FFI_SUCCESS;
3✔
252
   });
7✔
253
#else
254
   BOTAN_UNUSED(key, n, e);
255
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
256
#endif
257
}
258

259
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) {
1✔
260
   return botan_privkey_get_field(p, key, "p");
1✔
261
}
262

263
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) {
1✔
264
   return botan_privkey_get_field(q, key, "q");
1✔
265
}
266

267
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) {
1✔
268
   return botan_privkey_get_field(n, key, "n");
1✔
269
}
270

271
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
272
   return botan_privkey_get_field(e, key, "e");
1✔
273
}
274

275
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
1✔
276
   return botan_privkey_get_field(d, key, "d");
1✔
277
}
278

279
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
280
   return botan_pubkey_get_field(e, key, "e");
1✔
281
}
282

283
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
284
   return botan_pubkey_get_field(n, key, "n");
1✔
285
}
286

287
int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
4✔
288
#if defined(BOTAN_HAS_RSA)
289
   return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
14✔
290
      if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
291
         if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) {
292
            return write_vec_output(out, out_len, rsa->private_key_bits());
293
         } else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) {
294
            return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
295
         } else {
296
            return BOTAN_FFI_ERROR_BAD_FLAG;
297
         }
298
      } else {
299
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
300
      }
301
   });
302
#else
303
   BOTAN_UNUSED(rsa_key, out, out_len, flags);
304
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
305
#endif
306
}
307

308
/* DSA specific operations */
309
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
310
#if defined(BOTAN_HAS_DSA)
311

312
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
313
      return BOTAN_FFI_ERROR_NULL_POINTER;
314
   }
315

316
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
317
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
318
   }
319

320
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
321
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
322
      Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
1✔
323
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
1✔
324
      *key = new botan_privkey_struct(std::move(dsa));
2✔
325
      return BOTAN_FFI_SUCCESS;
2✔
326
   });
2✔
327
#else
328
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
329
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
330
#endif
331
}
332

333
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✔
334
#if defined(BOTAN_HAS_DSA)
335
   *key = nullptr;
2✔
336

337
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
338
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
339
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
2✔
340
      *key = new botan_privkey_struct(std::move(dsa));
4✔
341
      return BOTAN_FFI_SUCCESS;
4✔
342
   });
6✔
343
#else
344
   BOTAN_UNUSED(key, p, q, g, x);
345
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
346
#endif
347
}
348

349
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✔
350
#if defined(BOTAN_HAS_DSA)
351
   *key = nullptr;
2✔
352

353
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
354
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
355
      auto dsa = std::make_unique<Botan::DSA_PublicKey>(group, safe_get(y));
2✔
356
      *key = new botan_pubkey_struct(std::move(dsa));
4✔
357
      return BOTAN_FFI_SUCCESS;
2✔
358
   });
6✔
359
#else
360
   BOTAN_UNUSED(key, p, q, g, y);
361
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
362
#endif
363
}
364

365
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
366
   return botan_privkey_get_field(x, key, "x");
2✔
367
}
368

369
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
2✔
370
   return botan_pubkey_get_field(p, key, "p");
2✔
371
}
372

373
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) {
2✔
374
   return botan_pubkey_get_field(q, key, "q");
2✔
375
}
376

377
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
378
   return botan_pubkey_get_field(g, key, "g");
2✔
379
}
380

381
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
382
   return botan_pubkey_get_field(y, key, "y");
2✔
383
}
384

385
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
386
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
387
}
388

389
/* ECDSA specific operations */
390

391
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key) {
1✔
392
#if defined(BOTAN_HAS_ECC_KEY)
393
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
394
      const Botan::Public_Key& pub_key = safe_get(key);
1✔
395
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
1✔
396

397
      if(ec_key == nullptr) {
1✔
398
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
399
      }
400

401
      return ec_key->domain().used_explicit_encoding() ? 1 : 0;
1✔
402
   });
1✔
403
#else
404
   BOTAN_UNUSED(key);
405
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
406
#endif
407
}
408

409
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
410
                            const botan_mp_t public_x,
411
                            const botan_mp_t public_y,
412
                            const char* curve_name) {
413
#if defined(BOTAN_HAS_ECDSA)
414
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
415
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
416

417
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
418
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
419
         *key = new botan_pubkey_struct(std::move(p_key));
4✔
420
      }
421

422
      return rc;
2✔
423
   });
4✔
424
#else
425
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
426
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
427
#endif
428
}
429

430
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
431
#if defined(BOTAN_HAS_ECDSA)
432
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
433
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
2✔
434
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
2✔
435
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
436
         *key = new botan_privkey_struct(std::move(p_key));
4✔
437
      }
438
      return rc;
2✔
439
   });
4✔
440
#else
441
   BOTAN_UNUSED(key, scalar, curve_name);
442
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
443
#endif
444
}
445

446
/* ElGamal specific operations */
447
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
448
#if defined(BOTAN_HAS_ELGAMAL)
449

450
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
451
      return BOTAN_FFI_ERROR_NULL_POINTER;
452
   }
453

454
   if((pbits < 1024) || (qbits < 160)) {
1✔
455
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
456
   }
457

458
   Botan::DL_Group::PrimeType prime_type =
1✔
459
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
460

461
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
462
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
463
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
464
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
465
      *key = new botan_privkey_struct(std::move(elg));
2✔
466
      return BOTAN_FFI_SUCCESS;
2✔
467
   });
2✔
468
#else
469
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
470
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
471
#endif
472
}
473

474
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
2✔
475
#if defined(BOTAN_HAS_ELGAMAL)
476
   *key = nullptr;
2✔
477
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
478
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
479
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
2✔
480
      *key = new botan_pubkey_struct(std::move(elg));
4✔
481
      return BOTAN_FFI_SUCCESS;
2✔
482
   });
6✔
483
#else
484
   BOTAN_UNUSED(key, p, g, y);
485
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
486
#endif
487
}
488

489
int botan_privkey_load_elgamal(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
2✔
490
#if defined(BOTAN_HAS_ELGAMAL)
491
   *key = nullptr;
2✔
492
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
493
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
494
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(group, safe_get(x));
2✔
495
      *key = new botan_privkey_struct(std::move(elg));
4✔
496
      return BOTAN_FFI_SUCCESS;
4✔
497
   });
6✔
498
#else
499
   BOTAN_UNUSED(key, p, g, x);
500
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
501
#endif
502
}
503

504
/* Diffie Hellman specific operations */
505

506
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
507
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
508
}
509

510
int botan_privkey_load_dh(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
1✔
511
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
512
   *key = nullptr;
1✔
513
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
514
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
515
      auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
1✔
516
      *key = new botan_privkey_struct(std::move(dh));
2✔
517
      return BOTAN_FFI_SUCCESS;
2✔
518
   });
3✔
519
#else
520
   BOTAN_UNUSED(key, p, g, x);
521
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
522
#endif
523
}
524

525
int botan_pubkey_load_dh(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
1✔
526
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
527
   *key = nullptr;
1✔
528
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
529
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
530
      auto dh = std::make_unique<Botan::DH_PublicKey>(group, safe_get(y));
1✔
531
      *key = new botan_pubkey_struct(std::move(dh));
2✔
532
      return BOTAN_FFI_SUCCESS;
1✔
533
   });
3✔
534
#else
535
   BOTAN_UNUSED(key, p, g, y);
536
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
537
#endif
538
}
539

540
/* ECDH + x25519/x448 specific operations */
541

542
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
543
   if(param_str == nullptr) {
2✔
544
      return BOTAN_FFI_ERROR_NULL_POINTER;
545
   }
546

547
   const std::string params(param_str);
2✔
548

549
   if(params == "x25519" || params == "curve25519") {
2✔
550
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
551
   }
552

553
   if(params == "x448") {
2✔
554
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
555
   }
556

557
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
558
}
2✔
559

560
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
561
                           const botan_mp_t public_x,
562
                           const botan_mp_t public_y,
563
                           const char* curve_name) {
564
#if defined(BOTAN_HAS_ECDH)
565
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
566
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
567
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
568

569
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
570
         *key = new botan_pubkey_struct(std::move(p_key));
2✔
571
      }
572
      return rc;
1✔
573
   });
2✔
574
#else
575
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
576
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
577
#endif
578
}
579

580
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
4✔
581
#if defined(BOTAN_HAS_ECDH)
582
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
583
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
4✔
584
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
4✔
585
      if(rc == BOTAN_FFI_SUCCESS) {
4✔
586
         *key = new botan_privkey_struct(std::move(p_key));
8✔
587
      }
588
      return rc;
4✔
589
   });
8✔
590
#else
591
   BOTAN_UNUSED(key, scalar, curve_name);
592
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
593
#endif
594
}
595

596
/* SM2 specific operations */
597

598
int botan_pubkey_sm2_compute_za(
2✔
599
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
600
   if(out == nullptr || out_len == nullptr) {
2✔
601
      return BOTAN_FFI_ERROR_NULL_POINTER;
602
   }
603
   if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
604
      return BOTAN_FFI_ERROR_NULL_POINTER;
605
   }
606

607
#if defined(BOTAN_HAS_SM2)
608
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
609
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
610
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
611

612
      if(ec_key == nullptr) {
2✔
613
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
614
      }
615

616
      if(ec_key->algo_name() != "SM2") {
2✔
617
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
618
      }
619

620
      const std::string ident_str(ident);
2✔
621
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
622

623
      const std::vector<uint8_t> za =
2✔
624
         Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), ec_key->_public_ec_point());
2✔
625

626
      return write_vec_output(out, out_len, za);
2✔
627
   });
4✔
628
#else
629
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
630
#endif
631
}
632

633
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
634
                          const botan_mp_t public_x,
635
                          const botan_mp_t public_y,
636
                          const char* curve_name) {
637
#if defined(BOTAN_HAS_SM2)
638
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
639
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
3✔
640
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
3✔
641
         *key = new botan_pubkey_struct(std::move(p_key));
6✔
642
         return BOTAN_FFI_SUCCESS;
3✔
643
      }
644
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
645
   });
6✔
646
#else
647
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
648
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
649
#endif
650
}
651

652
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
653
#if defined(BOTAN_HAS_SM2)
654
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
655
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
656
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
657

658
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
659
         *key = new botan_privkey_struct(std::move(p_key));
6✔
660
      }
661
      return rc;
3✔
662
   });
6✔
663
#else
664
   BOTAN_UNUSED(key, scalar, curve_name);
665
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
666
#endif
667
}
668

669
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
670
                              const botan_mp_t public_x,
671
                              const botan_mp_t public_y,
672
                              const char* curve_name) {
673
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
674
}
675

676
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
677
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
678
}
679

680
/* Ed25519 specific operations */
681

682
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
683
#if defined(BOTAN_HAS_ED25519)
684
   *key = nullptr;
1✔
685
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
686
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
687
      auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
1✔
688
      *key = new botan_privkey_struct(std::move(ed25519));
2✔
689
      return BOTAN_FFI_SUCCESS;
2✔
690
   });
3✔
691
#else
692
   BOTAN_UNUSED(key, privkey);
693
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
694
#endif
695
}
696

697
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
698
#if defined(BOTAN_HAS_ED25519)
699
   *key = nullptr;
1✔
700
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
701
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
702
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
703
      *key = new botan_pubkey_struct(std::move(ed25519));
2✔
704
      return BOTAN_FFI_SUCCESS;
1✔
705
   });
3✔
706
#else
707
   BOTAN_UNUSED(key, pubkey);
708
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
709
#endif
710
}
711

712
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
713
#if defined(BOTAN_HAS_ED25519)
714
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
715
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
716
         const auto ed_key = ed->raw_private_key_bits();
717
         if(ed_key.size() != 64) {
718
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
719
         }
720
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
721
         return BOTAN_FFI_SUCCESS;
722
      } else {
723
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
724
      }
725
   });
726
#else
727
   BOTAN_UNUSED(key, output);
728
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
729
#endif
730
}
731

732
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
733
#if defined(BOTAN_HAS_ED25519)
734
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
735
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
736
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
737
         if(ed_key.size() != 32) {
738
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
739
         }
740
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
741
         return BOTAN_FFI_SUCCESS;
742
      } else {
743
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
744
      }
745
   });
746
#else
747
   BOTAN_UNUSED(key, output);
748
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
749
#endif
750
}
751

752
/* Ed448 specific operations */
753

754
int botan_privkey_load_ed448(botan_privkey_t* key, const uint8_t privkey[57]) {
1✔
755
#if defined(BOTAN_HAS_ED448)
756
   *key = nullptr;
1✔
757
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
758
      auto ed448 = std::make_unique<Botan::Ed448_PrivateKey>(std::span(privkey, 57));
1✔
759
      *key = new botan_privkey_struct(std::move(ed448));
2✔
760
      return BOTAN_FFI_SUCCESS;
1✔
761
   });
2✔
762
#else
763
   BOTAN_UNUSED(key, privkey);
764
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
765
#endif
766
}
767

768
int botan_pubkey_load_ed448(botan_pubkey_t* key, const uint8_t pubkey[57]) {
1✔
769
#if defined(BOTAN_HAS_ED448)
770
   *key = nullptr;
1✔
771
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
772
      auto ed448 = std::make_unique<Botan::Ed448_PublicKey>(std::span(pubkey, 57));
1✔
773
      *key = new botan_pubkey_struct(std::move(ed448));
2✔
774
      return BOTAN_FFI_SUCCESS;
1✔
775
   });
2✔
776
#else
777
   BOTAN_UNUSED(key, pubkey);
778
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
779
#endif
780
}
781

782
int botan_privkey_ed448_get_privkey(botan_privkey_t key, uint8_t output[57]) {
1✔
783
#if defined(BOTAN_HAS_ED448)
784
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
785
      if(auto ed = dynamic_cast<const Botan::Ed448_PrivateKey*>(&k)) {
786
         const auto ed_key = ed->raw_private_key_bits();
787
         Botan::copy_mem(std::span(output, 57), ed_key);
788
         return BOTAN_FFI_SUCCESS;
789
      } else {
790
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
791
      }
792
   });
793
#else
794
   BOTAN_UNUSED(key, output);
795
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
796
#endif
797
}
798

799
int botan_pubkey_ed448_get_pubkey(botan_pubkey_t key, uint8_t output[57]) {
1✔
800
#if defined(BOTAN_HAS_ED448)
801
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
3✔
802
      if(auto ed = dynamic_cast<const Botan::Ed448_PublicKey*>(&k)) {
803
         const auto ed_key = ed->public_key_bits();
804
         Botan::copy_mem(std::span(output, 57), ed_key);
805
         return BOTAN_FFI_SUCCESS;
806
      } else {
807
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
808
      }
809
   });
810
#else
811
   BOTAN_UNUSED(key, output);
812
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
813
#endif
814
}
815

816
/* X25519 specific operations */
817

818
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
819
#if defined(BOTAN_HAS_X25519)
820
   *key = nullptr;
1✔
821
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
822
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
823
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
1✔
824
      *key = new botan_privkey_struct(std::move(x25519));
2✔
825
      return BOTAN_FFI_SUCCESS;
2✔
826
   });
3✔
827
#else
828
   BOTAN_UNUSED(key, privkey);
829
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
830
#endif
831
}
832

833
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
834
#if defined(BOTAN_HAS_X25519)
835
   *key = nullptr;
1✔
836
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
837
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
838
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(pubkey_vec);
1✔
839
      *key = new botan_pubkey_struct(std::move(x25519));
2✔
840
      return BOTAN_FFI_SUCCESS;
1✔
841
   });
3✔
842
#else
843
   BOTAN_UNUSED(key, pubkey);
844
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
845
#endif
846
}
847

848
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
849
#if defined(BOTAN_HAS_X25519)
850
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
851
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
852
         const auto x25519_key = x25519->raw_private_key_bits();
853
         if(x25519_key.size() != 32) {
854
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
855
         }
856
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
857
         return BOTAN_FFI_SUCCESS;
858
      } else {
859
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
860
      }
861
   });
862
#else
863
   BOTAN_UNUSED(key, output);
864
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
865
#endif
866
}
867

868
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
869
#if defined(BOTAN_HAS_X25519)
870
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
871
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
872
         const std::vector<uint8_t>& x25519_key = x25519->public_value();
873
         if(x25519_key.size() != 32) {
874
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
875
         }
876
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
877
         return BOTAN_FFI_SUCCESS;
878
      } else {
879
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
880
      }
881
   });
882
#else
883
   BOTAN_UNUSED(key, output);
884
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
885
#endif
886
}
887

888
/* X448 specific operations */
889

890
int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
1✔
891
#if defined(BOTAN_HAS_X448)
892
   *key = nullptr;
1✔
893
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
894
      auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span(privkey, 56));
1✔
895
      *key = new botan_privkey_struct(std::move(x448));
2✔
896
      return BOTAN_FFI_SUCCESS;
1✔
897
   });
2✔
898
#else
899
   BOTAN_UNUSED(key, privkey);
900
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
901
#endif
902
}
903

904
int botan_pubkey_load_x448(botan_pubkey_t* key, const uint8_t pubkey[56]) {
1✔
905
#if defined(BOTAN_HAS_X448)
906
   *key = nullptr;
1✔
907
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
908
      auto x448 = std::make_unique<Botan::X448_PublicKey>(std::span(pubkey, 56));
1✔
909
      *key = new botan_pubkey_struct(std::move(x448));
2✔
910
      return BOTAN_FFI_SUCCESS;
1✔
911
   });
2✔
912
#else
913
   BOTAN_UNUSED(key, pubkey);
914
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
915
#endif
916
}
917

918
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56]) {
1✔
919
#if defined(BOTAN_HAS_X448)
920
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
921
      if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
922
         const auto x448_key = x448->raw_private_key_bits();
923
         Botan::copy_mem(std::span(output, 56), x448_key);
924
         return BOTAN_FFI_SUCCESS;
925
      } else {
926
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
927
      }
928
   });
929
#else
930
   BOTAN_UNUSED(key, output);
931
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
932
#endif
933
}
934

935
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
2✔
936
#if defined(BOTAN_HAS_X448)
937
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
938
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
939
         const std::vector<uint8_t>& x448_key = x448->public_value();
940
         Botan::copy_mem(std::span(output, 56), x448_key);
941
         return BOTAN_FFI_SUCCESS;
942
      } else {
943
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
944
      }
945
   });
946
#else
947
   BOTAN_UNUSED(key, output);
948
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
949
#endif
950
}
951

952
/*
953
* Algorithm specific key operations: Kyber
954
*/
955

956
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
957
#if defined(BOTAN_HAS_KYBER)
958
   *key = nullptr;
4✔
959
   switch(key_len) {
4✔
960
      case 1632:
1✔
961
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
962
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 1632);
1✔
963
            auto kyber512 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber512_R3);
1✔
964
            *key = new botan_privkey_struct(std::move(kyber512));
1✔
965
            return BOTAN_FFI_SUCCESS;
2✔
966
         });
2✔
967
      case 2400:
2✔
968
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
969
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
2✔
970
            auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768_R3);
2✔
971
            *key = new botan_privkey_struct(std::move(kyber768));
2✔
972
            return BOTAN_FFI_SUCCESS;
4✔
973
         });
4✔
974
      case 3168:
1✔
975
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
976
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 3168);
1✔
977
            auto kyber1024 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber1024_R3);
1✔
978
            *key = new botan_privkey_struct(std::move(kyber1024));
1✔
979
            return BOTAN_FFI_SUCCESS;
2✔
980
         });
2✔
981
      default:
982
         BOTAN_UNUSED(key, privkey, key_len);
983
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
984
   }
985
#else
986
   BOTAN_UNUSED(key, key_len, privkey);
987
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
988
#endif
989
}
990

991
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
992
#if defined(BOTAN_HAS_KYBER)
993
   *key = nullptr;
4✔
994
   switch(key_len) {
4✔
995
      case 800:
1✔
996
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
997
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 800);
1✔
998
            auto kyber512 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber512_R3);
1✔
999
            *key = new botan_pubkey_struct(std::move(kyber512));
2✔
1000
            return BOTAN_FFI_SUCCESS;
1✔
1001
         });
2✔
1002
      case 1184:
2✔
1003
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1004
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
2✔
1005
            auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768_R3);
2✔
1006
            *key = new botan_pubkey_struct(std::move(kyber768));
4✔
1007
            return BOTAN_FFI_SUCCESS;
2✔
1008
         });
4✔
1009
      case 1568:
1✔
1010
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
1011
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1568);
1✔
1012
            auto kyber1024 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber1024_R3);
1✔
1013
            *key = new botan_pubkey_struct(std::move(kyber1024));
2✔
1014
            return BOTAN_FFI_SUCCESS;
1✔
1015
         });
2✔
1016
      default:
1017
         BOTAN_UNUSED(key, pubkey, key_len);
1018
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1019
   }
1020
#else
1021
   BOTAN_UNUSED(key, pubkey, key_len);
1022
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1023
#endif
1024
}
1025

1026
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1027
#if defined(BOTAN_HAS_KYBER)
1028
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
12✔
1029
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1030
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1031
      } else {
1032
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1033
      }
1034
   });
1035
#else
1036
   BOTAN_UNUSED(key, ctx, view);
1037
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1038
#endif
1039
}
1040

1041
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1042
#if defined(BOTAN_HAS_KYBER)
1043
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1044
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1045
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1046
      } else {
1047
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1048
      }
1049
   });
1050
#else
1051
   BOTAN_UNUSED(key, ctx, view);
1052
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1053
#endif
1054
}
1055

1056
/*
1057
* Algorithm specific key operations: ML-KEM
1058
*/
1059

1060
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1061
#if defined(BOTAN_HAS_ML_KEM)
1062
   if(key == nullptr || privkey == nullptr || mlkem_mode == nullptr) {
4✔
1063
      return BOTAN_FFI_ERROR_NULL_POINTER;
1064
   }
1065

1066
   *key = nullptr;
4✔
1067

1068
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1069
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1070
      if(!mode.is_ml_kem()) {
4✔
1071
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1072
      }
1073

1074
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1075
      *key = new botan_privkey_struct(std::move(mlkem_key));
4✔
1076
      return BOTAN_FFI_SUCCESS;
4✔
1077
   });
4✔
1078
#else
1079
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1080
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1081
#endif
1082
}
1083

1084
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
4✔
1085
#if defined(BOTAN_HAS_ML_KEM)
1086
   if(key == nullptr || pubkey == nullptr || mlkem_mode == nullptr) {
4✔
1087
      return BOTAN_FFI_ERROR_NULL_POINTER;
1088
   }
1089

1090
   *key = nullptr;
4✔
1091

1092
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1093
      auto mode = Botan::ML_KEM_Mode(mlkem_mode);
4✔
1094
      if(!mode.is_ml_kem()) {
4✔
1095
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1096
      }
1097

1098
      auto mlkem_key = std::make_unique<Botan::ML_KEM_PublicKey>(std::span{pubkey, key_len}, mode.mode());
4✔
1099
      *key = new botan_pubkey_struct(std::move(mlkem_key));
8✔
1100
      return BOTAN_FFI_SUCCESS;
4✔
1101
   });
4✔
1102
#else
1103
   BOTAN_UNUSED(key, key_len, pubkey, mlkem_mode);
1104
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1105
#endif
1106
}
1107

1108
/*
1109
* Algorithm specific key operations: ML-DSA
1110
*/
1111

1112
int botan_privkey_load_ml_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mldsa_mode) {
4✔
1113
#if defined(BOTAN_HAS_ML_DSA)
1114
   if(key == nullptr || privkey == nullptr || mldsa_mode == nullptr) {
4✔
1115
      return BOTAN_FFI_ERROR_NULL_POINTER;
1116
   }
1117

1118
   *key = nullptr;
4✔
1119

1120
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1121
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1122
      if(!mode.is_ml_dsa()) {
4✔
1123
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1124
      }
1125

1126
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1127
      *key = new botan_privkey_struct(std::move(mldsa_key));
4✔
1128
      return BOTAN_FFI_SUCCESS;
4✔
1129
   });
4✔
1130
#else
1131
   BOTAN_UNUSED(key, key_len, privkey, mldsa_mode);
1132
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1133
#endif
1134
}
1135

1136
int botan_pubkey_load_ml_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mldsa_mode) {
4✔
1137
#if defined(BOTAN_HAS_ML_DSA)
1138
   if(key == nullptr || pubkey == nullptr || mldsa_mode == nullptr) {
4✔
1139
      return BOTAN_FFI_ERROR_NULL_POINTER;
1140
   }
1141

1142
   *key = nullptr;
4✔
1143

1144
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1145
      auto mode = Botan::ML_DSA_Mode(mldsa_mode);
4✔
1146
      if(!mode.is_ml_dsa()) {
4✔
1147
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1148
      }
1149

1150
      auto mldsa_key = std::make_unique<Botan::ML_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
4✔
1151
      *key = new botan_pubkey_struct(std::move(mldsa_key));
8✔
1152
      return BOTAN_FFI_SUCCESS;
4✔
1153
   });
4✔
1154
#else
1155
   BOTAN_UNUSED(key, key_len, pubkey, mldsa_mode);
1156
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1157
#endif
1158
}
1159

1160
/*
1161
* Algorithm specific key operations: SLH-DSA
1162
*/
1163

1164
int botan_privkey_load_slh_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1165
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1166
   if(key == nullptr || privkey == nullptr || slhdsa_mode == nullptr) {
13✔
1167
      return BOTAN_FFI_ERROR_NULL_POINTER;
1168
   }
1169

1170
   *key = nullptr;
13✔
1171

1172
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1173
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1174
      if(!mode.is_slh_dsa()) {
13✔
1175
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1176
      }
1177

1178
      auto slhdsa_key = std::make_unique<Botan::SLH_DSA_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1179
      *key = new botan_privkey_struct(std::move(slhdsa_key));
13✔
1180
      return BOTAN_FFI_SUCCESS;
13✔
1181
   });
13✔
1182
#else
1183
   BOTAN_UNUSED(key, key_len, privkey, slhdsa_mode);
1184
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1185
#endif
1186
}
1187

1188
int botan_pubkey_load_slh_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* slhdsa_mode) {
13✔
1189
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
1190
   if(key == nullptr || pubkey == nullptr || slhdsa_mode == nullptr) {
13✔
1191
      return BOTAN_FFI_ERROR_NULL_POINTER;
1192
   }
1193

1194
   *key = nullptr;
13✔
1195

1196
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1197
      auto mode = Botan::SLH_DSA_Parameters::create(slhdsa_mode);
13✔
1198
      if(!mode.is_slh_dsa()) {
13✔
1199
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1200
      }
1201

1202
      auto mldsa_key = std::make_unique<Botan::SLH_DSA_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1203
      *key = new botan_pubkey_struct(std::move(mldsa_key));
26✔
1204
      return BOTAN_FFI_SUCCESS;
13✔
1205
   });
13✔
1206
#else
1207
   BOTAN_UNUSED(key, key_len, pubkey, slhdsa_mode);
1208
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1209
#endif
1210
}
1211

1212
/*
1213
* Algorithm specific key operations: FrodoKEM
1214
*/
1215

1216
int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* frodo_mode) {
13✔
1217
#if defined(BOTAN_HAS_FRODOKEM)
1218
   if(key == nullptr || privkey == nullptr || frodo_mode == nullptr) {
13✔
1219
      return BOTAN_FFI_ERROR_NULL_POINTER;
1220
   }
1221

1222
   *key = nullptr;
13✔
1223

1224
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1225
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1226
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1227
      *key = new botan_privkey_struct(std::move(frodo_key));
13✔
1228
      return BOTAN_FFI_SUCCESS;
13✔
1229
   });
13✔
1230
#else
1231
   BOTAN_UNUSED(key, privkey, key_len, frodo_mode);
1232
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1233
#endif
1234
}
1235

1236
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode) {
13✔
1237
#if defined(BOTAN_HAS_FRODOKEM)
1238
   if(key == nullptr || pubkey == nullptr || frodo_mode == nullptr) {
13✔
1239
      return BOTAN_FFI_ERROR_NULL_POINTER;
1240
   }
1241

1242
   *key = nullptr;
13✔
1243

1244
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1245
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1246
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1247
      *key = new botan_pubkey_struct(std::move(frodo_key));
26✔
1248
      return BOTAN_FFI_SUCCESS;
13✔
1249
   });
13✔
1250
#else
1251
   BOTAN_UNUSED(key, pubkey, key_len, frodo_mode);
1252
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1253
#endif
1254
}
1255

1256
/*
1257
* Algorithm specific key operations : Classic McEliece
1258
*/
1259

1260
int botan_privkey_load_classic_mceliece(botan_privkey_t* key,
17✔
1261
                                        const uint8_t privkey[],
1262
                                        size_t key_len,
1263
                                        const char* cmce_mode) {
1264
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1265
   if(key == nullptr || privkey == nullptr || cmce_mode == nullptr) {
17✔
1266
      return BOTAN_FFI_ERROR_NULL_POINTER;
1267
   }
1268

1269
   *key = nullptr;
17✔
1270

1271
   return ffi_guard_thunk(__func__, [=]() -> int {
34✔
1272
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1273
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PrivateKey>(std::span{privkey, key_len}, mode);
17✔
1274
      *key = new botan_privkey_struct(std::move(cmce_key));
17✔
1275
      return BOTAN_FFI_SUCCESS;
17✔
1276
   });
17✔
1277
#else
1278
   BOTAN_UNUSED(key, privkey, key_len, cmce_mode);
1279
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1280
#endif
1281
}
1282

1283
int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
17✔
1284
                                       const uint8_t pubkey[],
1285
                                       size_t key_len,
1286
                                       const char* cmce_mode) {
1287
#if defined(BOTAN_HAS_CLASSICMCELIECE)
1288
   if(key == nullptr || pubkey == nullptr || cmce_mode == nullptr) {
17✔
1289
      return BOTAN_FFI_ERROR_NULL_POINTER;
1290
   }
1291

1292
   *key = nullptr;
17✔
1293

1294
   return ffi_guard_thunk(__func__, [=]() -> int {
34✔
1295
      const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
17✔
1296
      auto cmce_key = std::make_unique<Botan::Classic_McEliece_PublicKey>(std::span{pubkey, key_len}, mode);
17✔
1297
      *key = new botan_pubkey_struct(std::move(cmce_key));
34✔
1298
      return BOTAN_FFI_SUCCESS;
17✔
1299
   });
17✔
1300
#else
1301
   BOTAN_UNUSED(key, pubkey, key_len, cmce_mode);
1302
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1303
#endif
1304
}
1305

1306
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1307
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1308
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
1309
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1310
         auto pt = ecc->_public_ec_point().serialize_uncompressed();
1311
         return invoke_view_callback(view, ctx, pt);
1312
      } else {
1313
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1314
      }
1315
   });
1316
#else
1317
   BOTAN_UNUSED(key, view, ctx);
1318
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1319
#endif
1320
}
1321

1322
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1323
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1324
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1325
}
1✔
1326

1327
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1328
                         const char* aead,
1329
                         const uint8_t ct[],
1330
                         size_t ct_len,
1331
                         const uint8_t ad[],
1332
                         size_t ad_len,
1333
                         uint8_t out[],
1334
                         size_t* out_len) {
1335
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1336
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1337
}
1338

1339
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1340
                         botan_rng_t rng_obj,
1341
                         const char* aead,
1342
                         const uint8_t pt[],
1343
                         size_t pt_len,
1344
                         const uint8_t ad[],
1345
                         size_t ad_len,
1346
                         uint8_t out[],
1347
                         size_t* out_len) {
1348
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1349
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1350
}
1351
}
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