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

randombit / botan / 11331525401

14 Oct 2024 04:29PM UTC coverage: 91.093% (-0.03%) from 91.12%
11331525401

Pull #4291

github

web-flow
Merge f5ffe99f5 into ed74c9542
Pull Request #4291: PQC: SLH-DSA

90346 of 99180 relevant lines covered (91.09%)

9678761.99 hits per line

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

98.07
/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)
75
   #include <botan/kyber.h>
76
#endif
77

78
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
79
   #include <botan/sphincsplus.h>
80
#endif
81

82
namespace {
83

84
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
85

86
// These are always called within an existing try/catch block
87

88
template <class ECPrivateKey_t>
89
int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& scalar, const char* curve_name) {
9✔
90
   if(curve_name == nullptr) {
9✔
91
      return BOTAN_FFI_ERROR_NULL_POINTER;
92
   }
93

94
   Botan::Null_RNG null_rng;
9✔
95
   const auto grp = Botan::EC_Group::from_name(curve_name);
9✔
96
   key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
9✔
97
   return BOTAN_FFI_SUCCESS;
98
}
9✔
99

100
template <class ECPublicKey_t>
101
int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
6✔
102
                   const Botan::BigInt& public_x,
103
                   const Botan::BigInt& public_y,
104
                   const char* curve_name) {
105
   if(curve_name == nullptr) {
6✔
106
      return BOTAN_FFI_ERROR_NULL_POINTER;
107
   }
108

109
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
110

111
   if(auto pt = Botan::EC_AffinePoint::from_bigint_xy(group, public_x, public_y)) {
6✔
112
      key.reset(new ECPublicKey_t(group, pt->to_legacy_point()));
6✔
113
      return BOTAN_FFI_SUCCESS;
6✔
114
   } else {
115
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
116
   }
117
}
6✔
118

119
#endif
120

121
Botan::BigInt pubkey_get_field(const Botan::Public_Key& key, std::string_view field) {
40✔
122
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
123
   // Not currently handled by get_int_field
124
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
40✔
125
      if(field == "public_x") {
15✔
126
         return ecc->public_point().get_affine_x();
8✔
127
      } else if(field == "public_y") {
7✔
128
         return ecc->public_point().get_affine_y();
6✔
129
      }
130
   }
131
#endif
132

133
   try {
26✔
134
      return key.get_int_field(field);
26✔
135
   } catch(Botan::Unknown_PK_Field_Name&) {
2✔
136
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
2✔
137
   }
2✔
138
}
139

140
Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
35✔
141
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
142
   // Not currently handled by get_int_field
143
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
35✔
144
      if(field == "public_x") {
16✔
145
         return ecc->public_point().get_affine_x();
2✔
146
      } else if(field == "public_y") {
14✔
147
         return ecc->public_point().get_affine_y();
4✔
148
      }
149
   }
150
#endif
151

152
   try {
29✔
153
      return key.get_int_field(field);
29✔
154
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
155
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
156
   }
4✔
157
}
158

159
}  // namespace
160

161
extern "C" {
162

163
using namespace Botan_FFI;
164

165
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
166
   if(field_name_cstr == nullptr) {
40✔
167
      return BOTAN_FFI_ERROR_NULL_POINTER;
168
   }
169

170
   const std::string field_name(field_name_cstr);
40✔
171

172
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
173
}
40✔
174

175
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
176
   if(field_name_cstr == nullptr) {
35✔
177
      return BOTAN_FFI_ERROR_NULL_POINTER;
178
   }
179

180
   const std::string field_name(field_name_cstr);
35✔
181

182
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
140✔
183
}
35✔
184

185
/* RSA specific operations */
186

187
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
1✔
188
   if(n_bits < 1024 || n_bits > 16 * 1024) {
1✔
189
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
190
   }
191

192
   std::string n_str = std::to_string(n_bits);
1✔
193

194
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
195
}
1✔
196

197
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✔
198
#if defined(BOTAN_HAS_RSA)
199
   *key = nullptr;
2✔
200

201
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
202
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
2✔
203
      *key = new botan_privkey_struct(std::move(rsa));
2✔
204
      return BOTAN_FFI_SUCCESS;
2✔
205
   });
4✔
206
#else
207
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
208
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
209
#endif
210
}
211

212
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
213
#if defined(BOTAN_HAS_RSA)
214
   *key = nullptr;
1✔
215

216
   Botan::secure_vector<uint8_t> src(bits, bits + len);
1✔
217
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
218
      Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
1✔
219
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
1✔
220
      *key = new botan_privkey_struct(std::move(rsa));
1✔
221
      return BOTAN_FFI_SUCCESS;
1✔
222
   });
1✔
223
#else
224
   BOTAN_UNUSED(key, bits, len);
225
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
226
#endif
227
}
1✔
228

229
int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e) {
4✔
230
#if defined(BOTAN_HAS_RSA)
231
   *key = nullptr;
4✔
232
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
233
      auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
4✔
234
      *key = new botan_pubkey_struct(std::move(rsa));
6✔
235
      return BOTAN_FFI_SUCCESS;
3✔
236
   });
7✔
237
#else
238
   BOTAN_UNUSED(key, n, e);
239
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
240
#endif
241
}
242

243
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) {
1✔
244
   return botan_privkey_get_field(p, key, "p");
1✔
245
}
246

247
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) {
1✔
248
   return botan_privkey_get_field(q, key, "q");
1✔
249
}
250

251
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) {
1✔
252
   return botan_privkey_get_field(n, key, "n");
1✔
253
}
254

255
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
256
   return botan_privkey_get_field(e, key, "e");
1✔
257
}
258

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

263
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
264
   return botan_pubkey_get_field(e, key, "e");
1✔
265
}
266

267
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
268
   return botan_pubkey_get_field(n, key, "n");
1✔
269
}
270

271
int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
4✔
272
#if defined(BOTAN_HAS_RSA)
273
   return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
14✔
274
      if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
275
         if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
276
            return write_vec_output(out, out_len, rsa->private_key_bits());
277
         else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
278
            return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
279
         else
280
            return BOTAN_FFI_ERROR_BAD_FLAG;
281
      } else {
282
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
283
      }
284
   });
285
#else
286
   BOTAN_UNUSED(rsa_key, out, out_len, flags);
287
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
288
#endif
289
}
290

291
/* DSA specific operations */
292
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
293
#if defined(BOTAN_HAS_DSA)
294

295
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
296
      return BOTAN_FFI_ERROR_NULL_POINTER;
297
   }
298

299
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
300
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
301
   }
302

303
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
304
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
305
      Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
1✔
306
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
1✔
307
      *key = new botan_privkey_struct(std::move(dsa));
2✔
308
      return BOTAN_FFI_SUCCESS;
2✔
309
   });
2✔
310
#else
311
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
312
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
313
#endif
314
}
315

316
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✔
317
#if defined(BOTAN_HAS_DSA)
318
   *key = nullptr;
2✔
319

320
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
321
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
322
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
2✔
323
      *key = new botan_privkey_struct(std::move(dsa));
4✔
324
      return BOTAN_FFI_SUCCESS;
4✔
325
   });
6✔
326
#else
327
   BOTAN_UNUSED(key, p, q, g, x);
328
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
329
#endif
330
}
331

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

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

348
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
349
   return botan_privkey_get_field(x, key, "x");
2✔
350
}
351

352
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
2✔
353
   return botan_pubkey_get_field(p, key, "p");
2✔
354
}
355

356
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) {
2✔
357
   return botan_pubkey_get_field(q, key, "q");
2✔
358
}
359

360
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
361
   return botan_pubkey_get_field(g, key, "g");
2✔
362
}
363

364
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
365
   return botan_pubkey_get_field(y, key, "y");
2✔
366
}
367

368
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
369
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
370
}
371

372
/* ECDSA specific operations */
373

374
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key) {
1✔
375
#if defined(BOTAN_HAS_ECC_KEY)
376
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
377
      const Botan::Public_Key& pub_key = safe_get(key);
1✔
378
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
1✔
379

380
      if(ec_key == nullptr) {
1✔
381
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
382
      }
383

384
      return ec_key->domain().used_explicit_encoding() ? 1 : 0;
1✔
385
   });
1✔
386
#else
387
   BOTAN_UNUSED(key);
388
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
389
#endif
390
}
391

392
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
393
                            const botan_mp_t public_x,
394
                            const botan_mp_t public_y,
395
                            const char* curve_name) {
396
#if defined(BOTAN_HAS_ECDSA)
397
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
398
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
399

400
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
401
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
402
         *key = new botan_pubkey_struct(std::move(p_key));
4✔
403
      }
404

405
      return rc;
2✔
406
   });
2✔
407
#else
408
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
409
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
410
#endif
411
}
412

413
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
414
#if defined(BOTAN_HAS_ECDSA)
415
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
416
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
2✔
417
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
2✔
418
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
419
         *key = new botan_privkey_struct(std::move(p_key));
4✔
420
      }
421
      return rc;
2✔
422
   });
4✔
423
#else
424
   BOTAN_UNUSED(key, scalar, curve_name);
425
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
426
#endif
427
}
428

429
/* ElGamal specific operations */
430
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
431
#if defined(BOTAN_HAS_ELGAMAL)
432

433
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
434
      return BOTAN_FFI_ERROR_NULL_POINTER;
435
   }
436

437
   if((pbits < 1024) || (qbits < 160)) {
1✔
438
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
439
   }
440

441
   Botan::DL_Group::PrimeType prime_type =
1✔
442
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
443

444
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
445
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
446
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
447
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
448
      *key = new botan_privkey_struct(std::move(elg));
2✔
449
      return BOTAN_FFI_SUCCESS;
2✔
450
   });
2✔
451
#else
452
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
453
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
454
#endif
455
}
456

457
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
2✔
458
#if defined(BOTAN_HAS_ELGAMAL)
459
   *key = nullptr;
2✔
460
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
461
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
462
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
2✔
463
      *key = new botan_pubkey_struct(std::move(elg));
4✔
464
      return BOTAN_FFI_SUCCESS;
2✔
465
   });
6✔
466
#else
467
   BOTAN_UNUSED(key, p, g, y);
468
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
469
#endif
470
}
471

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

487
/* Diffie Hellman specific operations */
488

489
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
490
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
491
}
492

493
int botan_privkey_load_dh(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
1✔
494
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
495
   *key = nullptr;
1✔
496
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
497
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
498
      auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
1✔
499
      *key = new botan_privkey_struct(std::move(dh));
2✔
500
      return BOTAN_FFI_SUCCESS;
2✔
501
   });
3✔
502
#else
503
   BOTAN_UNUSED(key, p, g, x);
504
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
505
#endif
506
}
507

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

523
/* ECDH + x25519/x448 specific operations */
524

525
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
526
   if(param_str == nullptr) {
2✔
527
      return BOTAN_FFI_ERROR_NULL_POINTER;
528
   }
529

530
   const std::string params(param_str);
2✔
531

532
   if(params == "x25519" || params == "curve25519") {
2✔
533
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
534
   }
535

536
   if(params == "x448") {
2✔
537
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
538
   }
539

540
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
541
}
2✔
542

543
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
544
                           const botan_mp_t public_x,
545
                           const botan_mp_t public_y,
546
                           const char* curve_name) {
547
#if defined(BOTAN_HAS_ECDH)
548
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
549
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
550
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
551

552
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
553
         *key = new botan_pubkey_struct(std::move(p_key));
2✔
554
      }
555
      return rc;
1✔
556
   });
2✔
557
#else
558
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
559
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
560
#endif
561
}
562

563
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
4✔
564
#if defined(BOTAN_HAS_ECDH)
565
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
566
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
4✔
567
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
4✔
568
      if(rc == BOTAN_FFI_SUCCESS) {
4✔
569
         *key = new botan_privkey_struct(std::move(p_key));
8✔
570
      }
571
      return rc;
4✔
572
   });
8✔
573
#else
574
   BOTAN_UNUSED(key, scalar, curve_name);
575
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
576
#endif
577
}
578

579
/* SM2 specific operations */
580

581
int botan_pubkey_sm2_compute_za(
2✔
582
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
583
   if(out == nullptr || out_len == nullptr) {
2✔
584
      return BOTAN_FFI_ERROR_NULL_POINTER;
585
   }
586
   if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
587
      return BOTAN_FFI_ERROR_NULL_POINTER;
588
   }
589

590
#if defined(BOTAN_HAS_SM2)
591
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
592
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
593
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
594

595
      if(ec_key == nullptr) {
2✔
596
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
597
      }
598

599
      if(ec_key->algo_name() != "SM2") {
2✔
600
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
601
      }
602

603
      const std::string ident_str(ident);
2✔
604
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
605

606
      const std::vector<uint8_t> za = Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), ec_key->public_point());
2✔
607

608
      return write_vec_output(out, out_len, za);
2✔
609
   });
4✔
610
#else
611
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
612
#endif
613
}
614

615
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
616
                          const botan_mp_t public_x,
617
                          const botan_mp_t public_y,
618
                          const char* curve_name) {
619
#if defined(BOTAN_HAS_SM2)
620
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
621
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
3✔
622
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
3✔
623
         *key = new botan_pubkey_struct(std::move(p_key));
6✔
624
         return BOTAN_FFI_SUCCESS;
3✔
625
      }
626
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
627
   });
6✔
628
#else
629
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
630
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
631
#endif
632
}
633

634
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
635
#if defined(BOTAN_HAS_SM2)
636
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
637
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
638
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
639

640
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
641
         *key = new botan_privkey_struct(std::move(p_key));
6✔
642
      }
643
      return rc;
3✔
644
   });
6✔
645
#else
646
   BOTAN_UNUSED(key, scalar, curve_name);
647
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
648
#endif
649
}
650

651
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
652
                              const botan_mp_t public_x,
653
                              const botan_mp_t public_y,
654
                              const char* curve_name) {
655
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
656
}
657

658
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
659
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
660
}
661

662
/* Ed25519 specific operations */
663

664
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
665
#if defined(BOTAN_HAS_ED25519)
666
   *key = nullptr;
1✔
667
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
668
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
669
      auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
1✔
670
      *key = new botan_privkey_struct(std::move(ed25519));
2✔
671
      return BOTAN_FFI_SUCCESS;
2✔
672
   });
3✔
673
#else
674
   BOTAN_UNUSED(key, privkey);
675
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
676
#endif
677
}
678

679
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
680
#if defined(BOTAN_HAS_ED25519)
681
   *key = nullptr;
1✔
682
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
683
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
684
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
685
      *key = new botan_pubkey_struct(std::move(ed25519));
2✔
686
      return BOTAN_FFI_SUCCESS;
1✔
687
   });
3✔
688
#else
689
   BOTAN_UNUSED(key, pubkey);
690
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
691
#endif
692
}
693

694
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
695
#if defined(BOTAN_HAS_ED25519)
696
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
697
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
698
         const auto ed_key = ed->raw_private_key_bits();
699
         if(ed_key.size() != 64)
700
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
701
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
702
         return BOTAN_FFI_SUCCESS;
703
      } else {
704
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
705
      }
706
   });
707
#else
708
   BOTAN_UNUSED(key, output);
709
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
710
#endif
711
}
712

713
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
714
#if defined(BOTAN_HAS_ED25519)
715
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
716
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
717
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
718
         if(ed_key.size() != 32)
719
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
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
/* Ed448 specific operations */
733

734
int botan_privkey_load_ed448(botan_privkey_t* key, const uint8_t privkey[57]) {
1✔
735
#if defined(BOTAN_HAS_ED448)
736
   *key = nullptr;
1✔
737
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
738
      auto ed448 = std::make_unique<Botan::Ed448_PrivateKey>(std::span(privkey, 57));
1✔
739
      *key = new botan_privkey_struct(std::move(ed448));
2✔
740
      return BOTAN_FFI_SUCCESS;
1✔
741
   });
2✔
742
#else
743
   BOTAN_UNUSED(key, privkey);
744
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
745
#endif
746
}
747

748
int botan_pubkey_load_ed448(botan_pubkey_t* key, const uint8_t pubkey[57]) {
1✔
749
#if defined(BOTAN_HAS_ED448)
750
   *key = nullptr;
1✔
751
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
752
      auto ed448 = std::make_unique<Botan::Ed448_PublicKey>(std::span(pubkey, 57));
1✔
753
      *key = new botan_pubkey_struct(std::move(ed448));
2✔
754
      return BOTAN_FFI_SUCCESS;
1✔
755
   });
2✔
756
#else
757
   BOTAN_UNUSED(key, pubkey);
758
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
759
#endif
760
}
761

762
int botan_privkey_ed448_get_privkey(botan_privkey_t key, uint8_t output[57]) {
1✔
763
#if defined(BOTAN_HAS_ED448)
764
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
765
      if(auto ed = dynamic_cast<const Botan::Ed448_PrivateKey*>(&k)) {
766
         const auto ed_key = ed->raw_private_key_bits();
767
         Botan::copy_mem(std::span(output, 57), ed_key);
768
         return BOTAN_FFI_SUCCESS;
769
      } else {
770
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
771
      }
772
   });
773
#else
774
   BOTAN_UNUSED(key, output);
775
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
776
#endif
777
}
778

779
int botan_pubkey_ed448_get_pubkey(botan_pubkey_t key, uint8_t output[57]) {
1✔
780
#if defined(BOTAN_HAS_ED448)
781
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
3✔
782
      if(auto ed = dynamic_cast<const Botan::Ed448_PublicKey*>(&k)) {
783
         const auto ed_key = ed->public_key_bits();
784
         Botan::copy_mem(std::span(output, 57), ed_key);
785
         return BOTAN_FFI_SUCCESS;
786
      } else {
787
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
788
      }
789
   });
790
#else
791
   BOTAN_UNUSED(key, output);
792
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
793
#endif
794
}
795

796
/* X25519 specific operations */
797

798
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
799
#if defined(BOTAN_HAS_X25519)
800
   *key = nullptr;
1✔
801
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
802
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
803
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
1✔
804
      *key = new botan_privkey_struct(std::move(x25519));
2✔
805
      return BOTAN_FFI_SUCCESS;
2✔
806
   });
3✔
807
#else
808
   BOTAN_UNUSED(key, privkey);
809
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
810
#endif
811
}
812

813
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
814
#if defined(BOTAN_HAS_X25519)
815
   *key = nullptr;
1✔
816
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
817
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
818
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(pubkey_vec);
1✔
819
      *key = new botan_pubkey_struct(std::move(x25519));
2✔
820
      return BOTAN_FFI_SUCCESS;
1✔
821
   });
3✔
822
#else
823
   BOTAN_UNUSED(key, pubkey);
824
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
825
#endif
826
}
827

828
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
829
#if defined(BOTAN_HAS_X25519)
830
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
831
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
832
         const auto x25519_key = x25519->raw_private_key_bits();
833
         if(x25519_key.size() != 32)
834
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
835
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
836
         return BOTAN_FFI_SUCCESS;
837
      } else {
838
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
839
      }
840
   });
841
#else
842
   BOTAN_UNUSED(key, output);
843
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
844
#endif
845
}
846

847
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
848
#if defined(BOTAN_HAS_X25519)
849
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
850
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
851
         const std::vector<uint8_t>& x25519_key = x25519->public_value();
852
         if(x25519_key.size() != 32)
853
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
854
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
855
         return BOTAN_FFI_SUCCESS;
856
      } else {
857
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
858
      }
859
   });
860
#else
861
   BOTAN_UNUSED(key, output);
862
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
863
#endif
864
}
865

866
/* X448 specific operations */
867

868
int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
1✔
869
#if defined(BOTAN_HAS_X448)
870
   *key = nullptr;
1✔
871
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
872
      auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span(privkey, 56));
1✔
873
      *key = new botan_privkey_struct(std::move(x448));
2✔
874
      return BOTAN_FFI_SUCCESS;
1✔
875
   });
2✔
876
#else
877
   BOTAN_UNUSED(key, privkey);
878
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
879
#endif
880
}
881

882
int botan_pubkey_load_x448(botan_pubkey_t* key, const uint8_t pubkey[56]) {
1✔
883
#if defined(BOTAN_HAS_X448)
884
   *key = nullptr;
1✔
885
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
886
      auto x448 = std::make_unique<Botan::X448_PublicKey>(std::span(pubkey, 56));
1✔
887
      *key = new botan_pubkey_struct(std::move(x448));
2✔
888
      return BOTAN_FFI_SUCCESS;
1✔
889
   });
2✔
890
#else
891
   BOTAN_UNUSED(key, pubkey);
892
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
893
#endif
894
}
895

896
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56]) {
1✔
897
#if defined(BOTAN_HAS_X448)
898
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
899
      if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
900
         const auto x448_key = x448->raw_private_key_bits();
901
         Botan::copy_mem(std::span(output, 56), x448_key);
902
         return BOTAN_FFI_SUCCESS;
903
      } else {
904
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
905
      }
906
   });
907
#else
908
   BOTAN_UNUSED(key, output);
909
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
910
#endif
911
}
912

913
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
2✔
914
#if defined(BOTAN_HAS_X448)
915
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
916
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
917
         const std::vector<uint8_t>& x448_key = x448->public_value();
918
         Botan::copy_mem(std::span(output, 56), x448_key);
919
         return BOTAN_FFI_SUCCESS;
920
      } else {
921
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
922
      }
923
   });
924
#else
925
   BOTAN_UNUSED(key, output);
926
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
927
#endif
928
}
929

930
/*
931
* Algorithm specific key operations: SLH-DSA
932
*/
933

934
int botan_privkey_load_slh_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* slhdsa_mode) {
13✔
935
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
936
   if(key == nullptr || privkey == nullptr || slhdsa_mode == nullptr) {
13✔
937
      return BOTAN_FFI_ERROR_NULL_POINTER;
938
   }
939
   *key = nullptr;
13✔
940

941
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
942
      auto mode = Botan::Sphincs_Parameters::create(slhdsa_mode);
13✔
943
      if(!mode.is_slh_dsa()) {
13✔
944
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
945
      }
946

947
      auto slhdsa_key = std::make_unique<Botan::SphincsPlus_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
948
      *key = new botan_privkey_struct(std::move(slhdsa_key));
13✔
949
      return BOTAN_FFI_SUCCESS;
13✔
950
   });
13✔
951
#else
952
   BOTAN_UNUSED(key, key_len, privkey, slhdsa_mode);
953
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
954
#endif
955
}
956

957
int botan_pubkey_load_slh_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* slhdsa_mode) {
13✔
958
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
959
   *key = nullptr;
13✔
960

961
   if(pubkey == nullptr || slhdsa_mode == nullptr) {
13✔
962
      return BOTAN_FFI_ERROR_NULL_POINTER;
963
   }
964

965
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
966
      auto mode = Botan::Sphincs_Parameters::create(slhdsa_mode);
13✔
967
      if(!mode.is_slh_dsa()) {
13✔
968
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
969
      }
970

971
      auto mldsa_key = std::make_unique<Botan::SphincsPlus_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
972
      *key = new botan_pubkey_struct(std::move(mldsa_key));
26✔
973
      return BOTAN_FFI_SUCCESS;
13✔
974
   });
13✔
975
#else
976
   BOTAN_UNUSED(key, key_len, pubkey, slhdsa_mode);
977
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
978
#endif
979
}
980

981
/*
982
* Algorithm specific key operations: Kyber
983
*/
984

985
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
986
#if defined(BOTAN_HAS_KYBER)
987
   *key = nullptr;
4✔
988
   switch(key_len) {
4✔
989
      case 1632:
1✔
990
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
991
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 1632);
1✔
992
            auto kyber512 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber512_R3);
1✔
993
            *key = new botan_privkey_struct(std::move(kyber512));
1✔
994
            return BOTAN_FFI_SUCCESS;
2✔
995
         });
2✔
996
      case 2400:
2✔
997
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
998
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
2✔
999
            auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768_R3);
2✔
1000
            *key = new botan_privkey_struct(std::move(kyber768));
2✔
1001
            return BOTAN_FFI_SUCCESS;
4✔
1002
         });
4✔
1003
      case 3168:
1✔
1004
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
1005
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 3168);
1✔
1006
            auto kyber1024 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber1024_R3);
1✔
1007
            *key = new botan_privkey_struct(std::move(kyber1024));
1✔
1008
            return BOTAN_FFI_SUCCESS;
2✔
1009
         });
2✔
1010
      default:
1011
         BOTAN_UNUSED(key, privkey, key_len);
1012
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1013
   }
1014
#else
1015
   BOTAN_UNUSED(key, privkey);
1016
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1017
#endif
1018
}
1019

1020
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
1021
#if defined(BOTAN_HAS_KYBER)
1022
   *key = nullptr;
4✔
1023
   switch(key_len) {
4✔
1024
      case 800:
1✔
1025
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
1026
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 800);
1✔
1027
            auto kyber512 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber512_R3);
1✔
1028
            *key = new botan_pubkey_struct(std::move(kyber512));
2✔
1029
            return BOTAN_FFI_SUCCESS;
1✔
1030
         });
2✔
1031
      case 1184:
2✔
1032
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
1033
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
2✔
1034
            auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768_R3);
2✔
1035
            *key = new botan_pubkey_struct(std::move(kyber768));
4✔
1036
            return BOTAN_FFI_SUCCESS;
2✔
1037
         });
4✔
1038
      case 1568:
1✔
1039
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
1040
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1568);
1✔
1041
            auto kyber1024 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber1024_R3);
1✔
1042
            *key = new botan_pubkey_struct(std::move(kyber1024));
2✔
1043
            return BOTAN_FFI_SUCCESS;
1✔
1044
         });
2✔
1045
      default:
1046
         BOTAN_UNUSED(key, pubkey, key_len);
1047
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1048
   }
1049
#else
1050
   BOTAN_UNUSED(key, pubkey, key_len);
1051
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1052
#endif
1053
}
1054

1055
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1056
#if defined(BOTAN_HAS_KYBER)
1057
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
12✔
1058
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1059
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1060
      } else {
1061
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1062
      }
1063
   });
1064
#else
1065
   BOTAN_UNUSED(key, ctx, view);
1066
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1067
#endif
1068
}
1069

1070
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1071
#if defined(BOTAN_HAS_KYBER)
1072
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1073
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1074
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1075
      } else {
1076
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1077
      }
1078
   });
1079
#else
1080
   BOTAN_UNUSED(key, ctx, view);
1081
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1082
#endif
1083
}
1084

1085
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1086
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1087
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
1088
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1089
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
1090
         return invoke_view_callback(view, ctx, pt);
1091
      } else {
1092
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1093
      }
1094
   });
1095
#else
1096
   BOTAN_UNUSED(key, view, ctx);
1097
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1098
#endif
1099
}
1100

1101
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1102
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1103
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1104
}
1✔
1105

1106
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1107
                         const char* aead,
1108
                         const uint8_t ct[],
1109
                         size_t ct_len,
1110
                         const uint8_t ad[],
1111
                         size_t ad_len,
1112
                         uint8_t out[],
1113
                         size_t* out_len) {
1114
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1115
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1116
}
1117

1118
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1119
                         botan_rng_t rng_obj,
1120
                         const char* aead,
1121
                         const uint8_t pt[],
1122
                         size_t pt_len,
1123
                         const uint8_t ad[],
1124
                         size_t ad_len,
1125
                         uint8_t out[],
1126
                         size_t* out_len) {
1127
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1128
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1129
}
1130
}
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