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

randombit / botan / 11327544235

14 Oct 2024 12:28PM UTC coverage: 91.125% (+0.005%) from 91.12%
11327544235

Pull #3893

github

web-flow
Merge a2498c19d into ed74c9542
Pull Request #3893: PQC: ML-KEM

90382 of 99185 relevant lines covered (91.12%)

9134193.3 hits per line

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

98.1
/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_ML_KEM)
75
   #include <botan/kyber.h>
76
   #include <botan/internal/kyber_constants.h>
77
#endif
78

79
namespace {
80

81
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
82

83
// These are always called within an existing try/catch block
84

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

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

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

106
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
107

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

116
#endif
117

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

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

137
Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
35✔
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)) {
35✔
141
      if(field == "public_x") {
16✔
142
         return ecc->public_point().get_affine_x();
2✔
143
      } else if(field == "public_y") {
14✔
144
         return ecc->public_point().get_affine_y();
4✔
145
      }
146
   }
147
#endif
148

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

156
}  // namespace
157

158
extern "C" {
159

160
using namespace Botan_FFI;
161

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

167
   const std::string field_name(field_name_cstr);
40✔
168

169
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
170
}
40✔
171

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

177
   const std::string field_name(field_name_cstr);
35✔
178

179
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
140✔
180
}
35✔
181

182
/* RSA specific operations */
183

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

189
   std::string n_str = std::to_string(n_bits);
1✔
190

191
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
192
}
1✔
193

194
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✔
195
#if defined(BOTAN_HAS_RSA)
196
   *key = nullptr;
2✔
197

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

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

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

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

240
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) {
1✔
241
   return botan_privkey_get_field(p, key, "p");
1✔
242
}
243

244
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) {
1✔
245
   return botan_privkey_get_field(q, key, "q");
1✔
246
}
247

248
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) {
1✔
249
   return botan_privkey_get_field(n, key, "n");
1✔
250
}
251

252
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
253
   return botan_privkey_get_field(e, key, "e");
1✔
254
}
255

256
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
1✔
257
   return botan_privkey_get_field(d, key, "d");
1✔
258
}
259

260
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
261
   return botan_pubkey_get_field(e, key, "e");
1✔
262
}
263

264
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
265
   return botan_pubkey_get_field(n, key, "n");
1✔
266
}
267

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

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

292
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
293
      return BOTAN_FFI_ERROR_NULL_POINTER;
294
   }
295

296
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
297
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
298
   }
299

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

313
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✔
314
#if defined(BOTAN_HAS_DSA)
315
   *key = nullptr;
2✔
316

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

329
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✔
330
#if defined(BOTAN_HAS_DSA)
331
   *key = nullptr;
2✔
332

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

345
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
346
   return botan_privkey_get_field(x, key, "x");
2✔
347
}
348

349
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
2✔
350
   return botan_pubkey_get_field(p, key, "p");
2✔
351
}
352

353
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) {
2✔
354
   return botan_pubkey_get_field(q, key, "q");
2✔
355
}
356

357
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
358
   return botan_pubkey_get_field(g, key, "g");
2✔
359
}
360

361
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
362
   return botan_pubkey_get_field(y, key, "y");
2✔
363
}
364

365
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
366
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
367
}
368

369
/* ECDSA specific operations */
370

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

377
      if(ec_key == nullptr) {
1✔
378
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
379
      }
380

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

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

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

402
      return rc;
2✔
403
   });
4✔
404
#else
405
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
406
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
407
#endif
408
}
409

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

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

430
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
431
      return BOTAN_FFI_ERROR_NULL_POINTER;
432
   }
433

434
   if((pbits < 1024) || (qbits < 160)) {
1✔
435
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
436
   }
437

438
   Botan::DL_Group::PrimeType prime_type =
1✔
439
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
440

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

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

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

484
/* Diffie Hellman specific operations */
485

486
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
487
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
488
}
489

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

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

520
/* ECDH + x25519/x448 specific operations */
521

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

527
   const std::string params(param_str);
2✔
528

529
   if(params == "x25519" || params == "curve25519") {
2✔
530
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
531
   }
532

533
   if(params == "x448") {
2✔
534
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
535
   }
536

537
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
538
}
2✔
539

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

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

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

576
/* SM2 specific operations */
577

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

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

592
      if(ec_key == nullptr) {
2✔
593
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
594
      }
595

596
      if(ec_key->algo_name() != "SM2") {
2✔
597
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
598
      }
599

600
      const std::string ident_str(ident);
2✔
601
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
602

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

605
      return write_vec_output(out, out_len, za);
2✔
606
   });
4✔
607
#else
608
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
609
#endif
610
}
611

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

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

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

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

655
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
656
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
657
}
658

659
/* Ed25519 specific operations */
660

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

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

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

710
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
711
#if defined(BOTAN_HAS_ED25519)
712
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
713
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
714
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
715
         if(ed_key.size() != 32)
716
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
717
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
718
         return BOTAN_FFI_SUCCESS;
719
      } else {
720
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
721
      }
722
   });
723
#else
724
   BOTAN_UNUSED(key, output);
725
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
726
#endif
727
}
728

729
/* Ed448 specific operations */
730

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

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

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

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

793
/* X25519 specific operations */
794

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

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

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

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

863
/* X448 specific operations */
864

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

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

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

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

927
/*
928
* Algorithm specific key operations: Kyber
929
*/
930

931
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
932
#if defined(BOTAN_HAS_KYBER)
933
   *key = nullptr;
4✔
934
   switch(key_len) {
4✔
935
      case 1632:
1✔
936
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
937
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 1632);
1✔
938
            auto kyber512 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber512_R3);
1✔
939
            *key = new botan_privkey_struct(std::move(kyber512));
1✔
940
            return BOTAN_FFI_SUCCESS;
2✔
941
         });
2✔
942
      case 2400:
2✔
943
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
944
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
2✔
945
            auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768_R3);
2✔
946
            *key = new botan_privkey_struct(std::move(kyber768));
2✔
947
            return BOTAN_FFI_SUCCESS;
4✔
948
         });
4✔
949
      case 3168:
1✔
950
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
951
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 3168);
1✔
952
            auto kyber1024 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber1024_R3);
1✔
953
            *key = new botan_privkey_struct(std::move(kyber1024));
1✔
954
            return BOTAN_FFI_SUCCESS;
2✔
955
         });
2✔
956
      default:
957
         BOTAN_UNUSED(key, privkey, key_len);
958
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
959
   }
960
#else
961
   BOTAN_UNUSED(key, key_len, privkey);
962
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
963
#endif
964
}
965

966
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
967
#if defined(BOTAN_HAS_KYBER)
968
   *key = nullptr;
4✔
969
   switch(key_len) {
4✔
970
      case 800:
1✔
971
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
972
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 800);
1✔
973
            auto kyber512 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber512_R3);
1✔
974
            *key = new botan_pubkey_struct(std::move(kyber512));
2✔
975
            return BOTAN_FFI_SUCCESS;
1✔
976
         });
2✔
977
      case 1184:
2✔
978
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
979
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
2✔
980
            auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768_R3);
2✔
981
            *key = new botan_pubkey_struct(std::move(kyber768));
4✔
982
            return BOTAN_FFI_SUCCESS;
2✔
983
         });
4✔
984
      case 1568:
1✔
985
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
986
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1568);
1✔
987
            auto kyber1024 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber1024_R3);
1✔
988
            *key = new botan_pubkey_struct(std::move(kyber1024));
2✔
989
            return BOTAN_FFI_SUCCESS;
1✔
990
         });
2✔
991
      default:
992
         BOTAN_UNUSED(key, pubkey, key_len);
993
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
994
   }
995
#else
996
   BOTAN_UNUSED(key, pubkey, key_len);
997
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
998
#endif
999
}
1000

1001
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1002
#if defined(BOTAN_HAS_KYBER)
1003
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
12✔
1004
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1005
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1006
      } else {
1007
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1008
      }
1009
   });
1010
#else
1011
   BOTAN_UNUSED(key, ctx, view);
1012
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1013
#endif
1014
}
1015

1016
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1017
#if defined(BOTAN_HAS_KYBER)
1018
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1019
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1020
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1021
      } else {
1022
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1023
      }
1024
   });
1025
#else
1026
   BOTAN_UNUSED(key, ctx, view);
1027
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1028
#endif
1029
}
1030

1031
/*
1032
* Algorithm specific key operations: ML-KEM
1033
*/
1034

1035
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
6✔
1036
#if defined(BOTAN_HAS_ML_KEM)
1037
   *key = nullptr;
6✔
1038

1039
   if(privkey == nullptr || mlkem_mode == nullptr) {
6✔
1040
      return BOTAN_FFI_ERROR_NULL_POINTER;
1041
   }
1042

1043
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
1044
      auto mode = Botan::KyberConstants(Botan::KyberMode(mlkem_mode));
6✔
1045
      if(!mode.mode().is_ml_kem()) {
6✔
1046
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1047
      }
1048

1049
      if(key_len != mode.private_key_bytes()) {
3✔
1050
         return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
1051
      }
1052

1053
      auto mlkem_key = std::make_unique<Botan::Kyber_PrivateKey>(std::span{privkey, key_len}, mode.mode());
3✔
1054
      *key = new botan_privkey_struct(std::move(mlkem_key));
3✔
1055
      return BOTAN_FFI_SUCCESS;
3✔
1056
   });
6✔
1057
#else
1058
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1059
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1060
#endif
1061
}
1062

1063
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
6✔
1064
#if defined(BOTAN_HAS_ML_KEM)
1065
   *key = nullptr;
6✔
1066

1067
   if(pubkey == nullptr || mlkem_mode == nullptr) {
6✔
1068
      return BOTAN_FFI_ERROR_NULL_POINTER;
1069
   }
1070

1071
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
1072
      auto mode = Botan::KyberConstants(Botan::KyberMode(mlkem_mode));
6✔
1073
      if(!mode.mode().is_ml_kem()) {
6✔
1074
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1075
      }
1076

1077
      if(key_len != mode.public_key_bytes()) {
3✔
1078
         return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
1079
      }
1080

1081
      auto mlkem_key = std::make_unique<Botan::Kyber_PublicKey>(std::span{pubkey, key_len}, mode.mode());
3✔
1082
      *key = new botan_pubkey_struct(std::move(mlkem_key));
6✔
1083
      return BOTAN_FFI_SUCCESS;
3✔
1084
   });
6✔
1085
#else
1086
   BOTAN_UNUSED(key, key_len, pubkey, mlkem_mode);
1087
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1088
#endif
1089
}
1090

1091
int botan_privkey_view_ml_kem_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
3✔
1092
#if defined(BOTAN_HAS_ML_KEM)
1093
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
9✔
1094
      if(auto mlkem_kem = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1095
         return invoke_view_callback(view, ctx, mlkem_kem->raw_private_key_bits());
1096
      } else {
1097
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1098
      }
1099
   });
1100
#else
1101
   BOTAN_UNUSED(key, ctx, view);
1102
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1103
#endif
1104
}
1105

1106
int botan_pubkey_view_ml_kem_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1107
#if defined(BOTAN_HAS_ML_KEM)
1108
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
1109
      if(auto mlkem_key = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1110
         return invoke_view_callback(view, ctx, mlkem_key->raw_public_key_bits());
1111
      } else {
1112
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1113
      }
1114
   });
1115
#else
1116
   BOTAN_UNUSED(key, ctx, view);
1117
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1118
#endif
1119
}
1120

1121
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1122
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1123
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
1124
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1125
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
1126
         return invoke_view_callback(view, ctx, pt);
1127
      } else {
1128
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1129
      }
1130
   });
1131
#else
1132
   BOTAN_UNUSED(key, view, ctx);
1133
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1134
#endif
1135
}
1136

1137
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1138
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1139
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1140
}
1✔
1141

1142
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1143
                         const char* aead,
1144
                         const uint8_t ct[],
1145
                         size_t ct_len,
1146
                         const uint8_t ad[],
1147
                         size_t ad_len,
1148
                         uint8_t out[],
1149
                         size_t* out_len) {
1150
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1151
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1152
}
1153

1154
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1155
                         botan_rng_t rng_obj,
1156
                         const char* aead,
1157
                         const uint8_t pt[],
1158
                         size_t pt_len,
1159
                         const uint8_t ad[],
1160
                         size_t ad_len,
1161
                         uint8_t out[],
1162
                         size_t* out_len) {
1163
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1164
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1165
}
1166
}
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