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

randombit / botan / 11345717360

15 Oct 2024 12:09PM UTC coverage: 91.512% (+0.4%) from 91.131%
11345717360

push

github

web-flow
Merge pull request #4270 from Rohde-Schwarz/feature/ml-dsa-ipd-after-refactoring

PQC: ML-DSA

73266 of 80062 relevant lines covered (91.51%)

11223399.72 hits per line

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

98.24
/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
#if defined(BOTAN_HAS_FRODOKEM)
80
   #include <botan/frodokem.h>
81
#endif
82

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

87
namespace {
88

89
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
90

91
// These are always called within an existing try/catch block
92

93
template <class ECPrivateKey_t>
94
int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& scalar, const char* curve_name) {
9✔
95
   if(curve_name == nullptr) {
9✔
96
      return BOTAN_FFI_ERROR_NULL_POINTER;
97
   }
98

99
   Botan::Null_RNG null_rng;
9✔
100
   const auto grp = Botan::EC_Group::from_name(curve_name);
9✔
101
   key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
9✔
102
   return BOTAN_FFI_SUCCESS;
103
}
9✔
104

105
template <class ECPublicKey_t>
106
int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
6✔
107
                   const Botan::BigInt& public_x,
108
                   const Botan::BigInt& public_y,
109
                   const char* curve_name) {
110
   if(curve_name == nullptr) {
6✔
111
      return BOTAN_FFI_ERROR_NULL_POINTER;
112
   }
113

114
   const auto group = Botan::EC_Group::from_name(curve_name);
6✔
115

116
   if(auto pt = Botan::EC_AffinePoint::from_bigint_xy(group, public_x, public_y)) {
6✔
117
      key.reset(new ECPublicKey_t(group, pt->to_legacy_point()));
6✔
118
      return BOTAN_FFI_SUCCESS;
6✔
119
   } else {
120
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
121
   }
122
}
6✔
123

124
#endif
125

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

138
   try {
26✔
139
      return key.get_int_field(field);
26✔
140
   } catch(Botan::Unknown_PK_Field_Name&) {
2✔
141
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
2✔
142
   }
2✔
143
}
144

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

157
   try {
29✔
158
      return key.get_int_field(field);
29✔
159
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
160
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
161
   }
4✔
162
}
163

164
}  // namespace
165

166
extern "C" {
167

168
using namespace Botan_FFI;
169

170
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
171
   if(field_name_cstr == nullptr) {
40✔
172
      return BOTAN_FFI_ERROR_NULL_POINTER;
173
   }
174

175
   const std::string field_name(field_name_cstr);
40✔
176

177
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
158✔
178
}
40✔
179

180
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
181
   if(field_name_cstr == nullptr) {
35✔
182
      return BOTAN_FFI_ERROR_NULL_POINTER;
183
   }
184

185
   const std::string field_name(field_name_cstr);
35✔
186

187
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
140✔
188
}
35✔
189

190
/* RSA specific operations */
191

192
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
1✔
193
   if(n_bits < 1024 || n_bits > 16 * 1024) {
1✔
194
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
195
   }
196

197
   std::string n_str = std::to_string(n_bits);
1✔
198

199
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
200
}
1✔
201

202
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✔
203
#if defined(BOTAN_HAS_RSA)
204
   *key = nullptr;
2✔
205

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

217
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
218
#if defined(BOTAN_HAS_RSA)
219
   *key = nullptr;
1✔
220

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

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

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

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

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

260
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
261
   return botan_privkey_get_field(e, key, "e");
1✔
262
}
263

264
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) {
1✔
265
   return botan_privkey_get_field(d, key, "d");
1✔
266
}
267

268
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
269
   return botan_pubkey_get_field(e, key, "e");
1✔
270
}
271

272
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
273
   return botan_pubkey_get_field(n, key, "n");
1✔
274
}
275

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

296
/* DSA specific operations */
297
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
298
#if defined(BOTAN_HAS_DSA)
299

300
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
301
      return BOTAN_FFI_ERROR_NULL_POINTER;
302
   }
303

304
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
305
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
306
   }
307

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

321
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✔
322
#if defined(BOTAN_HAS_DSA)
323
   *key = nullptr;
2✔
324

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

337
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✔
338
#if defined(BOTAN_HAS_DSA)
339
   *key = nullptr;
2✔
340

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

353
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
354
   return botan_privkey_get_field(x, key, "x");
2✔
355
}
356

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

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

365
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
366
   return botan_pubkey_get_field(g, key, "g");
2✔
367
}
368

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

373
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
374
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
375
}
376

377
/* ECDSA specific operations */
378

379
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key) {
1✔
380
#if defined(BOTAN_HAS_ECC_KEY)
381
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
382
      const Botan::Public_Key& pub_key = safe_get(key);
1✔
383
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
1✔
384

385
      if(ec_key == nullptr) {
1✔
386
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
387
      }
388

389
      return ec_key->domain().used_explicit_encoding() ? 1 : 0;
1✔
390
   });
1✔
391
#else
392
   BOTAN_UNUSED(key);
393
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
394
#endif
395
}
396

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

405
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
406
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
407
         *key = new botan_pubkey_struct(std::move(p_key));
4✔
408
      }
409

410
      return rc;
2✔
411
   });
4✔
412
#else
413
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
414
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
415
#endif
416
}
417

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

434
/* ElGamal specific operations */
435
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
436
#if defined(BOTAN_HAS_ELGAMAL)
437

438
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
439
      return BOTAN_FFI_ERROR_NULL_POINTER;
440
   }
441

442
   if((pbits < 1024) || (qbits < 160)) {
1✔
443
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
444
   }
445

446
   Botan::DL_Group::PrimeType prime_type =
1✔
447
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
448

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

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

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

492
/* Diffie Hellman specific operations */
493

494
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
495
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
496
}
497

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

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

528
/* ECDH + x25519/x448 specific operations */
529

530
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
531
   if(param_str == nullptr) {
2✔
532
      return BOTAN_FFI_ERROR_NULL_POINTER;
533
   }
534

535
   const std::string params(param_str);
2✔
536

537
   if(params == "x25519" || params == "curve25519") {
2✔
538
      return botan_privkey_create(key_obj, "X25519", "", rng_obj);
×
539
   }
540

541
   if(params == "x448") {
2✔
542
      return botan_privkey_create(key_obj, "X448", "", rng_obj);
×
543
   }
544

545
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
546
}
2✔
547

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

557
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
558
         *key = new botan_pubkey_struct(std::move(p_key));
2✔
559
      }
560
      return rc;
1✔
561
   });
2✔
562
#else
563
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
564
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
565
#endif
566
}
567

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

584
/* SM2 specific operations */
585

586
int botan_pubkey_sm2_compute_za(
2✔
587
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
588
   if(out == nullptr || out_len == nullptr) {
2✔
589
      return BOTAN_FFI_ERROR_NULL_POINTER;
590
   }
591
   if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
592
      return BOTAN_FFI_ERROR_NULL_POINTER;
593
   }
594

595
#if defined(BOTAN_HAS_SM2)
596
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
597
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
598
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
599

600
      if(ec_key == nullptr) {
2✔
601
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
602
      }
603

604
      if(ec_key->algo_name() != "SM2") {
2✔
605
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
606
      }
607

608
      const std::string ident_str(ident);
2✔
609
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
610

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

613
      return write_vec_output(out, out_len, za);
2✔
614
   });
4✔
615
#else
616
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
617
#endif
618
}
619

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

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

645
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
646
         *key = new botan_privkey_struct(std::move(p_key));
6✔
647
      }
648
      return rc;
3✔
649
   });
6✔
650
#else
651
   BOTAN_UNUSED(key, scalar, curve_name);
652
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
653
#endif
654
}
655

656
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
657
                              const botan_mp_t public_x,
658
                              const botan_mp_t public_y,
659
                              const char* curve_name) {
660
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
661
}
662

663
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
664
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
665
}
666

667
/* Ed25519 specific operations */
668

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

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

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

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

737
/* Ed448 specific operations */
738

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

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

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

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

801
/* X25519 specific operations */
802

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

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

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

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

871
/* X448 specific operations */
872

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

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

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

918
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
2✔
919
#if defined(BOTAN_HAS_X448)
920
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
921
      if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
922
         const std::vector<uint8_t>& x448_key = x448->public_value();
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
/*
936
* Algorithm specific key operations: Kyber
937
*/
938

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

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

1009
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
1010
#if defined(BOTAN_HAS_KYBER)
1011
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
12✔
1012
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1013
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1014
      } else {
1015
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1016
      }
1017
   });
1018
#else
1019
   BOTAN_UNUSED(key, ctx, view);
1020
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1021
#endif
1022
}
1023

1024
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
1025
#if defined(BOTAN_HAS_KYBER)
1026
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
1027
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1028
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
1029
      } else {
1030
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1031
      }
1032
   });
1033
#else
1034
   BOTAN_UNUSED(key, ctx, view);
1035
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1036
#endif
1037
}
1038

1039
/*
1040
* Algorithm specific key operations: ML-KEM
1041
*/
1042

1043
int botan_privkey_load_ml_kem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mlkem_mode) {
4✔
1044
#if defined(BOTAN_HAS_ML_KEM)
1045
   if(key == nullptr || privkey == nullptr || mlkem_mode == nullptr) {
4✔
1046
      return BOTAN_FFI_ERROR_NULL_POINTER;
1047
   }
1048

1049
   *key = nullptr;
4✔
1050

1051
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1052
      auto mode = Botan::KyberConstants(Botan::KyberMode(mlkem_mode));
4✔
1053
      if(!mode.mode().is_ml_kem()) {
4✔
1054
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1055
      }
1056

1057
      if(key_len != mode.private_key_bytes()) {
4✔
1058
         return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
1059
      }
1060

1061
      auto mlkem_key = std::make_unique<Botan::Kyber_PrivateKey>(std::span{privkey, key_len}, mode.mode());
4✔
1062
      *key = new botan_privkey_struct(std::move(mlkem_key));
4✔
1063
      return BOTAN_FFI_SUCCESS;
4✔
1064
   });
4✔
1065
#else
1066
   BOTAN_UNUSED(key, key_len, privkey, mlkem_mode);
1067
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1068
#endif
1069
}
1070

1071
int botan_pubkey_load_ml_kem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mlkem_mode) {
4✔
1072
#if defined(BOTAN_HAS_ML_KEM)
1073
   if(key == nullptr || pubkey == nullptr || mlkem_mode == nullptr) {
4✔
1074
      return BOTAN_FFI_ERROR_NULL_POINTER;
1075
   }
1076

1077
   *key = nullptr;
4✔
1078

1079
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1080
      auto mode = Botan::KyberConstants(Botan::KyberMode(mlkem_mode));
4✔
1081
      if(!mode.mode().is_ml_kem()) {
4✔
1082
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1083
      }
1084

1085
      if(key_len != mode.public_key_bytes()) {
4✔
1086
         return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
1087
      }
1088

1089
      auto mlkem_key = std::make_unique<Botan::Kyber_PublicKey>(std::span{pubkey, key_len}, mode.mode());
4✔
1090
      *key = new botan_pubkey_struct(std::move(mlkem_key));
8✔
1091
      return BOTAN_FFI_SUCCESS;
4✔
1092
   });
4✔
1093
#else
1094
   BOTAN_UNUSED(key, key_len, pubkey, mlkem_mode);
1095
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1096
#endif
1097
}
1098

1099
/*
1100
* Algorithm specific key operations: ML-DSA
1101
*/
1102

1103
int botan_privkey_load_ml_dsa(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* mldsa_mode) {
4✔
1104
#if defined(BOTAN_HAS_ML_DSA)
1105
   if(key == nullptr || privkey == nullptr || mldsa_mode == nullptr) {
4✔
1106
      return BOTAN_FFI_ERROR_NULL_POINTER;
1107
   }
1108

1109
   *key = nullptr;
4✔
1110

1111
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1112
      auto mode = Botan::DilithiumMode(mldsa_mode);
4✔
1113
      if(!mode.is_ml_dsa()) {
4✔
1114
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1115
      }
1116

1117
      auto mldsa_key = std::make_unique<Botan::Dilithium_PrivateKey>(std::span{privkey, key_len}, mode);
4✔
1118
      *key = new botan_privkey_struct(std::move(mldsa_key));
4✔
1119
      return BOTAN_FFI_SUCCESS;
4✔
1120
   });
4✔
1121
#else
1122
   BOTAN_UNUSED(key, key_len, privkey, mldsa_mode);
1123
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1124
#endif
1125
}
1126

1127
int botan_pubkey_load_ml_dsa(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* mldsa_mode) {
4✔
1128
#if defined(BOTAN_HAS_ML_DSA)
1129
   if(key == nullptr || pubkey == nullptr || mldsa_mode == nullptr) {
4✔
1130
      return BOTAN_FFI_ERROR_NULL_POINTER;
1131
   }
1132

1133
   *key = nullptr;
4✔
1134

1135
   return ffi_guard_thunk(__func__, [=]() -> int {
8✔
1136
      auto mode = Botan::DilithiumMode(mldsa_mode);
4✔
1137
      if(!mode.is_ml_dsa()) {
4✔
1138
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1139
      }
1140

1141
      auto mldsa_key = std::make_unique<Botan::Dilithium_PublicKey>(std::span{pubkey, key_len}, mode);
4✔
1142
      *key = new botan_pubkey_struct(std::move(mldsa_key));
8✔
1143
      return BOTAN_FFI_SUCCESS;
4✔
1144
   });
4✔
1145
#else
1146
   BOTAN_UNUSED(key, key_len, pubkey, mldsa_mode);
1147
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1148
#endif
1149
}
1150

1151
/*
1152
* Algorithm specific key operations: FrodoKEM
1153
*/
1154

1155
int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], size_t key_len, const char* frodo_mode) {
13✔
1156
#if defined(BOTAN_HAS_FRODOKEM)
1157
   if(key == nullptr || privkey == nullptr || frodo_mode == nullptr) {
13✔
1158
      return BOTAN_FFI_ERROR_NULL_POINTER;
1159
   }
1160

1161
   *key = nullptr;
13✔
1162

1163
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1164
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1165
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PrivateKey>(std::span{privkey, key_len}, mode);
13✔
1166
      *key = new botan_privkey_struct(std::move(frodo_key));
13✔
1167
      return BOTAN_FFI_SUCCESS;
13✔
1168
   });
13✔
1169
#else
1170
   BOTAN_UNUSED(key, privkey, key_len, frodo_mode);
1171
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1172
#endif
1173
}
1174

1175
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode) {
13✔
1176
#if defined(BOTAN_HAS_FRODOKEM)
1177
   if(key == nullptr || pubkey == nullptr || frodo_mode == nullptr) {
13✔
1178
      return BOTAN_FFI_ERROR_NULL_POINTER;
1179
   }
1180

1181
   *key = nullptr;
13✔
1182

1183
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
1184
      const auto mode = Botan::FrodoKEMMode(frodo_mode);
13✔
1185
      auto frodo_key = std::make_unique<Botan::FrodoKEM_PublicKey>(std::span{pubkey, key_len}, mode);
13✔
1186
      *key = new botan_pubkey_struct(std::move(frodo_key));
26✔
1187
      return BOTAN_FFI_SUCCESS;
13✔
1188
   });
13✔
1189
#else
1190
   BOTAN_UNUSED(key, pubkey, key_len, frodo_mode);
1191
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1192
#endif
1193
}
1194

1195
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
1196
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1197
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
1198
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1199
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
1200
         return invoke_view_callback(view, ctx, pt);
1201
      } else {
1202
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
1203
      }
1204
   });
1205
#else
1206
   BOTAN_UNUSED(key, view, ctx);
1207
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1208
#endif
1209
}
1210

1211
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
1212
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
3✔
1213
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
1214
}
1✔
1215

1216
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
1217
                         const char* aead,
1218
                         const uint8_t ct[],
1219
                         size_t ct_len,
1220
                         const uint8_t ad[],
1221
                         size_t ad_len,
1222
                         uint8_t out[],
1223
                         size_t* out_len) {
1224
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
1225
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1226
}
1227

1228
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
1229
                         botan_rng_t rng_obj,
1230
                         const char* aead,
1231
                         const uint8_t pt[],
1232
                         size_t pt_len,
1233
                         const uint8_t ad[],
1234
                         size_t ad_len,
1235
                         uint8_t out[],
1236
                         size_t* out_len) {
1237
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
1238
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
1239
}
1240
}
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