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

randombit / botan / 5890505464

17 Aug 2023 11:45AM UTC coverage: 91.716% (+0.007%) from 91.709%
5890505464

push

github

randombit
Merge GH #3667 Add Python argon2 interface

78581 of 85679 relevant lines covered (91.72%)

8394432.28 hits per line

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

98.03
/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_CURVE_25519)
51
   #include <botan/curve25519.h>
52
#endif
53

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

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

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

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

70
namespace {
71

72
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
73

74
// These are always called within an existing try/catch block
75

76
template <class ECPrivateKey_t>
77
int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& scalar, const char* curve_name) {
9✔
78
   if(curve_name == nullptr) {
9✔
79
      return BOTAN_FFI_ERROR_NULL_POINTER;
80
   }
81

82
   Botan::Null_RNG null_rng;
9✔
83
   Botan::EC_Group grp(curve_name);
9✔
84
   key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
9✔
85
   return BOTAN_FFI_SUCCESS;
86
}
9✔
87

88
template <class ECPublicKey_t>
89
int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
6✔
90
                   const Botan::BigInt& public_x,
91
                   const Botan::BigInt& public_y,
92
                   const char* curve_name) {
93
   if(curve_name == nullptr) {
6✔
94
      return BOTAN_FFI_ERROR_NULL_POINTER;
95
   }
96

97
   Botan::EC_Group grp(curve_name);
6✔
98
   Botan::EC_Point uncompressed_point = grp.point(public_x, public_y);
6✔
99
   key.reset(new ECPublicKey_t(grp, uncompressed_point));
6✔
100
   return BOTAN_FFI_SUCCESS;
101
}
6✔
102

103
#endif
104

105
Botan::BigInt pubkey_get_field(const Botan::Public_Key& key, std::string_view field) {
40✔
106
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
107
   // Not currently handled by get_int_field
108
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
40✔
109
      if(field == "public_x") {
21✔
110
         return ecc->public_point().get_affine_x();
8✔
111
      } else if(field == "public_y") {
7✔
112
         return ecc->public_point().get_affine_y();
6✔
113
      }
114
   }
115
#endif
116

117
   try {
26✔
118
      return key.get_int_field(field);
64✔
119
   } catch(Botan::Unknown_PK_Field_Name&) {
2✔
120
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
2✔
121
   }
2✔
122
}
123

124
Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
35✔
125
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
126
   // Not currently handled by get_int_field
127
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
35✔
128
      if(field == "public_x") {
20✔
129
         return ecc->public_point().get_affine_x();
2✔
130
      } else if(field == "public_y") {
14✔
131
         return ecc->public_point().get_affine_y();
4✔
132
      }
133
   }
134
#endif
135

136
   try {
29✔
137
      return key.get_int_field(field);
60✔
138
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
139
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
140
   }
4✔
141
}
142

143
}  // namespace
144

145
extern "C" {
146

147
using namespace Botan_FFI;
148

149
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
150
   if(field_name_cstr == nullptr) {
40✔
151
      return BOTAN_FFI_ERROR_NULL_POINTER;
152
   }
153

154
   const std::string field_name(field_name_cstr);
40✔
155

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

159
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
160
   if(field_name_cstr == nullptr) {
35✔
161
      return BOTAN_FFI_ERROR_NULL_POINTER;
162
   }
163

164
   const std::string field_name(field_name_cstr);
35✔
165

166
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
140✔
167
}
35✔
168

169
/* RSA specific operations */
170

171
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
1✔
172
   if(n_bits < 1024 || n_bits > 16 * 1024) {
1✔
173
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
174
   }
175

176
   std::string n_str = std::to_string(n_bits);
1✔
177

178
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
179
}
1✔
180

181
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✔
182
#if defined(BOTAN_HAS_RSA)
183
   *key = nullptr;
2✔
184

185
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
186
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
2✔
187
      *key = new botan_privkey_struct(std::move(rsa));
2✔
188
      return BOTAN_FFI_SUCCESS;
2✔
189
   });
4✔
190
#else
191
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
192
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
193
#endif
194
}
195

196
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
197
#if defined(BOTAN_HAS_RSA)
198
   *key = nullptr;
1✔
199

200
   Botan::secure_vector<uint8_t> src(bits, bits + len);
1✔
201
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
202
      Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
1✔
203
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
1✔
204
      *key = new botan_privkey_struct(std::move(rsa));
1✔
205
      return BOTAN_FFI_SUCCESS;
1✔
206
   });
1✔
207
#else
208
   BOTAN_UNUSED(key, bits, len);
209
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
210
#endif
211
}
1✔
212

213
int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e) {
4✔
214
#if defined(BOTAN_HAS_RSA)
215
   *key = nullptr;
4✔
216
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
217
      auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
4✔
218
      *key = new botan_pubkey_struct(std::move(rsa));
6✔
219
      return BOTAN_FFI_SUCCESS;
3✔
220
   });
7✔
221
#else
222
   BOTAN_UNUSED(key, n, e);
223
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
224
#endif
225
}
226

227
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) {
1✔
228
   return botan_privkey_get_field(p, key, "p");
1✔
229
}
230

231
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) {
1✔
232
   return botan_privkey_get_field(q, key, "q");
1✔
233
}
234

235
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) {
1✔
236
   return botan_privkey_get_field(n, key, "n");
1✔
237
}
238

239
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) {
1✔
240
   return botan_privkey_get_field(e, key, "e");
1✔
241
}
242

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

247
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) {
1✔
248
   return botan_pubkey_get_field(e, key, "e");
1✔
249
}
250

251
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) {
1✔
252
   return botan_pubkey_get_field(n, key, "n");
1✔
253
}
254

255
int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
4✔
256
#if defined(BOTAN_HAS_RSA)
257
   return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
16✔
258
      if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
259
         if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
260
            return write_vec_output(out, out_len, rsa->private_key_bits());
261
         else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
262
            return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
263
         else
264
            return BOTAN_FFI_ERROR_BAD_FLAG;
265
      } else {
266
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
267
      }
268
   });
269
#else
270
   BOTAN_UNUSED(rsa_key, out, out_len, flags);
271
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
272
#endif
273
}
274

275
/* DSA specific operations */
276
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
277
#if defined(BOTAN_HAS_DSA)
278

279
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
280
      return BOTAN_FFI_ERROR_NULL_POINTER;
281
   }
282

283
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
284
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
285
   }
286

287
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
288
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
289
      Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
1✔
290
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
1✔
291
      *key = new botan_privkey_struct(std::move(dsa));
2✔
292
      return BOTAN_FFI_SUCCESS;
2✔
293
   });
2✔
294
#else
295
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
296
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
297
#endif
298
}
299

300
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✔
301
#if defined(BOTAN_HAS_DSA)
302
   *key = nullptr;
2✔
303

304
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
305
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
306
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
2✔
307
      *key = new botan_privkey_struct(std::move(dsa));
4✔
308
      return BOTAN_FFI_SUCCESS;
4✔
309
   });
6✔
310
#else
311
   BOTAN_UNUSED(key, p, q, g, x);
312
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
313
#endif
314
}
315

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

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

332
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) {
2✔
333
   return botan_privkey_get_field(x, key, "x");
2✔
334
}
335

336
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) {
2✔
337
   return botan_pubkey_get_field(p, key, "p");
2✔
338
}
339

340
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) {
2✔
341
   return botan_pubkey_get_field(q, key, "q");
2✔
342
}
343

344
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) {
2✔
345
   return botan_pubkey_get_field(g, key, "g");
2✔
346
}
347

348
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) {
2✔
349
   return botan_pubkey_get_field(y, key, "y");
2✔
350
}
351

352
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
353
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
354
}
355

356
/* ECDSA specific operations */
357

358
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key) {
1✔
359
#if defined(BOTAN_HAS_ECC_KEY)
360
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
361
      const Botan::Public_Key& pub_key = safe_get(key);
1✔
362
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
1✔
363

364
      if(ec_key == nullptr) {
1✔
365
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
366
      }
367

368
      return ec_key->domain().used_explicit_encoding() ? 1 : 0;
1✔
369
   });
1✔
370
#else
371
   BOTAN_UNUSED(key);
372
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
373
#endif
374
}
375

376
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
377
                            const botan_mp_t public_x,
378
                            const botan_mp_t public_y,
379
                            const char* curve_name) {
380
#if defined(BOTAN_HAS_ECDSA)
381
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
382
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
383

384
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
385
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
386
         *key = new botan_pubkey_struct(std::move(p_key));
4✔
387
      }
388

389
      return rc;
2✔
390
   });
4✔
391
#else
392
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
393
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
394
#endif
395
}
396

397
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
398
#if defined(BOTAN_HAS_ECDSA)
399
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
400
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
2✔
401
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
2✔
402
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
403
         *key = new botan_privkey_struct(std::move(p_key));
4✔
404
      }
405
      return rc;
2✔
406
   });
4✔
407
#else
408
   BOTAN_UNUSED(key, scalar, curve_name);
409
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
410
#endif
411
}
412

413
/* ElGamal specific operations */
414
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
415
#if defined(BOTAN_HAS_ELGAMAL)
416

417
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
418
      return BOTAN_FFI_ERROR_NULL_POINTER;
419
   }
420

421
   if((pbits < 1024) || (qbits < 160)) {
1✔
422
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
423
   }
424

425
   Botan::DL_Group::PrimeType prime_type =
1✔
426
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
427

428
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
429
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
430
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
431
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
432
      *key = new botan_privkey_struct(std::move(elg));
2✔
433
      return BOTAN_FFI_SUCCESS;
2✔
434
   });
2✔
435
#else
436
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
437
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
438
#endif
439
}
440

441
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
2✔
442
#if defined(BOTAN_HAS_ELGAMAL)
443
   *key = nullptr;
2✔
444
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
445
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
446
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
2✔
447
      *key = new botan_pubkey_struct(std::move(elg));
4✔
448
      return BOTAN_FFI_SUCCESS;
2✔
449
   });
6✔
450
#else
451
   BOTAN_UNUSED(key, p, g, y);
452
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
453
#endif
454
}
455

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

471
/* Diffie Hellman specific operations */
472

473
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
474
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
475
}
476

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

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

507
/* ECDH + x25519 specific operations */
508

509
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
510
   if(param_str == nullptr) {
2✔
511
      return BOTAN_FFI_ERROR_NULL_POINTER;
512
   }
513

514
   const std::string params(param_str);
2✔
515

516
   if(params == "curve25519") {
2✔
517
      return botan_privkey_create(key_obj, "Curve25519", "", rng_obj);
×
518
   }
519

520
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
521
}
2✔
522

523
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
524
                           const botan_mp_t public_x,
525
                           const botan_mp_t public_y,
526
                           const char* curve_name) {
527
#if defined(BOTAN_HAS_ECDH)
528
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
529
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
530
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
531

532
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
533
         *key = new botan_pubkey_struct(std::move(p_key));
2✔
534
      }
535
      return rc;
1✔
536
   });
2✔
537
#else
538
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
539
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
540
#endif
541
}
542

543
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
4✔
544
#if defined(BOTAN_HAS_ECDH)
545
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
546
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
4✔
547
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
4✔
548
      if(rc == BOTAN_FFI_SUCCESS) {
4✔
549
         *key = new botan_privkey_struct(std::move(p_key));
8✔
550
      }
551
      return rc;
4✔
552
   });
8✔
553
#else
554
   BOTAN_UNUSED(key, scalar, curve_name);
555
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
556
#endif
557
}
558

559
/* SM2 specific operations */
560

561
int botan_pubkey_sm2_compute_za(
2✔
562
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
563
   if(out == nullptr || out_len == nullptr) {
2✔
564
      return BOTAN_FFI_ERROR_NULL_POINTER;
565
   }
566
   if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
567
      return BOTAN_FFI_ERROR_NULL_POINTER;
568
   }
569

570
#if defined(BOTAN_HAS_SM2)
571
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
572
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
573
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
574

575
      if(ec_key == nullptr) {
2✔
576
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
577
      }
578

579
      if(ec_key->algo_name() != "SM2") {
2✔
580
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
581
      }
582

583
      const std::string ident_str(ident);
2✔
584
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
585

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

588
      return write_vec_output(out, out_len, za);
2✔
589
   });
6✔
590
#else
591
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
592
#endif
593
}
594

595
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
596
                          const botan_mp_t public_x,
597
                          const botan_mp_t public_y,
598
                          const char* curve_name) {
599
#if defined(BOTAN_HAS_SM2)
600
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
601
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
3✔
602
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
3✔
603
         *key = new botan_pubkey_struct(std::move(p_key));
6✔
604
         return BOTAN_FFI_SUCCESS;
3✔
605
      }
606
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
607
   });
6✔
608
#else
609
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
610
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
611
#endif
612
}
613

614
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
615
#if defined(BOTAN_HAS_SM2)
616
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
617
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
618
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
619

620
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
621
         *key = new botan_privkey_struct(std::move(p_key));
6✔
622
      }
623
      return rc;
3✔
624
   });
6✔
625
#else
626
   BOTAN_UNUSED(key, scalar, curve_name);
627
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
628
#endif
629
}
630

631
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
632
                              const botan_mp_t public_x,
633
                              const botan_mp_t public_y,
634
                              const char* curve_name) {
635
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
636
}
637

638
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
639
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
640
}
641

642
/* Ed25519 specific operations */
643

644
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
645
#if defined(BOTAN_HAS_ED25519)
646
   *key = nullptr;
1✔
647
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
648
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
649
      auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
1✔
650
      *key = new botan_privkey_struct(std::move(ed25519));
2✔
651
      return BOTAN_FFI_SUCCESS;
2✔
652
   });
3✔
653
#else
654
   BOTAN_UNUSED(key, privkey);
655
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
656
#endif
657
}
658

659
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
660
#if defined(BOTAN_HAS_ED25519)
661
   *key = nullptr;
1✔
662
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
663
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
664
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
665
      *key = new botan_pubkey_struct(std::move(ed25519));
2✔
666
      return BOTAN_FFI_SUCCESS;
1✔
667
   });
3✔
668
#else
669
   BOTAN_UNUSED(key, pubkey);
670
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
671
#endif
672
}
673

674
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
675
#if defined(BOTAN_HAS_ED25519)
676
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
677
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
678
         const auto ed_key = ed->raw_private_key_bits();
679
         if(ed_key.size() != 64)
680
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
681
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
682
         return BOTAN_FFI_SUCCESS;
683
      } else {
684
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
685
      }
686
   });
687
#else
688
   BOTAN_UNUSED(key, output);
689
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
690
#endif
691
}
692

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

712
/* X25519 specific operations */
713

714
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
715
#if defined(BOTAN_HAS_X25519)
716
   *key = nullptr;
1✔
717
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
718
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
719
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
1✔
720
      *key = new botan_privkey_struct(std::move(x25519));
2✔
721
      return BOTAN_FFI_SUCCESS;
2✔
722
   });
3✔
723
#else
724
   BOTAN_UNUSED(key, privkey);
725
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
726
#endif
727
}
728

729
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
730
#if defined(BOTAN_HAS_X25519)
731
   *key = nullptr;
1✔
732
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
733
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
734
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(pubkey_vec);
1✔
735
      *key = new botan_pubkey_struct(std::move(x25519));
2✔
736
      return BOTAN_FFI_SUCCESS;
1✔
737
   });
3✔
738
#else
739
   BOTAN_UNUSED(key, pubkey);
740
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
741
#endif
742
}
743

744
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
745
#if defined(BOTAN_HAS_X25519)
746
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
747
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
748
         const auto x25519_key = x25519->raw_private_key_bits();
749
         if(x25519_key.size() != 32)
750
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
751
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
752
         return BOTAN_FFI_SUCCESS;
753
      } else {
754
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
755
      }
756
   });
757
#else
758
   BOTAN_UNUSED(key, output);
759
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
760
#endif
761
}
762

763
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
764
#if defined(BOTAN_HAS_X25519)
765
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
766
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
767
         const std::vector<uint8_t>& x25519_key = x25519->public_value();
768
         if(x25519_key.size() != 32)
769
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
770
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
771
         return BOTAN_FFI_SUCCESS;
772
      } else {
773
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
774
      }
775
   });
776
#else
777
   BOTAN_UNUSED(key, output);
778
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
779
#endif
780
}
781

782
/*
783
* Algorithm specific key operations: Kyber
784
*/
785

786
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
787
#if defined(BOTAN_HAS_KYBER)
788
   *key = nullptr;
4✔
789
   switch(key_len) {
4✔
790
      case 1632:
1✔
791
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
792
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 1632);
1✔
793
            auto kyber512 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber512);
1✔
794
            *key = new botan_privkey_struct(std::move(kyber512));
1✔
795
            return BOTAN_FFI_SUCCESS;
2✔
796
         });
2✔
797
      case 2400:
2✔
798
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
799
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
2✔
800
            auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768);
2✔
801
            *key = new botan_privkey_struct(std::move(kyber768));
2✔
802
            return BOTAN_FFI_SUCCESS;
4✔
803
         });
4✔
804
      case 3168:
1✔
805
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
806
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 3168);
1✔
807
            auto kyber1024 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber1024);
1✔
808
            *key = new botan_privkey_struct(std::move(kyber1024));
1✔
809
            return BOTAN_FFI_SUCCESS;
2✔
810
         });
2✔
811
      default:
812
         BOTAN_UNUSED(key, privkey, key_len);
813
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
814
   }
815
#else
816
   BOTAN_UNUSED(key, privkey);
817
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
818
#endif
819
}
820

821
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
822
#if defined(BOTAN_HAS_KYBER)
823
   *key = nullptr;
4✔
824
   switch(key_len) {
4✔
825
      case 800:
1✔
826
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
827
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 800);
1✔
828
            auto kyber512 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber512);
1✔
829
            *key = new botan_pubkey_struct(std::move(kyber512));
2✔
830
            return BOTAN_FFI_SUCCESS;
1✔
831
         });
2✔
832
      case 1184:
2✔
833
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
834
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
2✔
835
            auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768);
2✔
836
            *key = new botan_pubkey_struct(std::move(kyber768));
4✔
837
            return BOTAN_FFI_SUCCESS;
2✔
838
         });
4✔
839
      case 1568:
1✔
840
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
841
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1568);
1✔
842
            auto kyber1024 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber1024);
1✔
843
            *key = new botan_pubkey_struct(std::move(kyber1024));
2✔
844
            return BOTAN_FFI_SUCCESS;
1✔
845
         });
2✔
846
      default:
847
         BOTAN_UNUSED(key, pubkey, key_len);
848
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
849
   }
850
#else
851
   BOTAN_UNUSED(key, pubkey, key_len);
852
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
853
#endif
854
}
855

856
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
857
#if defined(BOTAN_HAS_KYBER)
858
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
12✔
859
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
860
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
861
      } else {
862
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
863
      }
864
   });
865
#else
866
   BOTAN_UNUSED(key, ctx, view);
867
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
868
#endif
869
}
870

871
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
872
#if defined(BOTAN_HAS_KYBER)
873
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
874
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
875
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
876
      } else {
877
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
878
      }
879
   });
880
#else
881
   BOTAN_UNUSED(key, ctx, view);
882
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
883
#endif
884
}
885

886
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
887
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
888
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
889
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
890
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
891
         return invoke_view_callback(view, ctx, pt);
892
      } else {
893
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
894
      }
895
   });
896
#else
897
   BOTAN_UNUSED(key, view, ctx);
898
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
899
#endif
900
}
901

902
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
903
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
2✔
904
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
905
}
1✔
906

907
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
908
                         const char* aead,
909
                         const uint8_t ct[],
910
                         size_t ct_len,
911
                         const uint8_t ad[],
912
                         size_t ad_len,
913
                         uint8_t out[],
914
                         size_t* out_len) {
915
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
916
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
917
}
918

919
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
920
                         botan_rng_t rng_obj,
921
                         const char* aead,
922
                         const uint8_t pt[],
923
                         size_t pt_len,
924
                         const uint8_t ad[],
925
                         size_t ad_len,
926
                         uint8_t out[],
927
                         size_t* out_len) {
928
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
929
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
930
}
931
}
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