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

randombit / botan / 5111374265

29 May 2023 11:19AM UTC coverage: 92.227% (+0.5%) from 91.723%
5111374265

push

github

randombit
Next release will be 3.1.0. Update release notes

75588 of 81959 relevant lines covered (92.23%)

11886470.91 hits per line

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

97.54
/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
namespace {
67

68
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
69

70
// These are always called within an existing try/catch block
71

72
template <class ECPrivateKey_t>
73
int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& scalar, const char* curve_name) {
9✔
74
   if(curve_name == nullptr)
9✔
75
      return BOTAN_FFI_ERROR_NULL_POINTER;
76

77
   Botan::Null_RNG null_rng;
9✔
78
   Botan::EC_Group grp(curve_name);
9✔
79
   key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
9✔
80
   return BOTAN_FFI_SUCCESS;
81
}
9✔
82

83
template <class ECPublicKey_t>
84
int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
6✔
85
                   const Botan::BigInt& public_x,
86
                   const Botan::BigInt& public_y,
87
                   const char* curve_name) {
88
   if(curve_name == nullptr)
6✔
89
      return BOTAN_FFI_ERROR_NULL_POINTER;
90

91
   Botan::EC_Group grp(curve_name);
6✔
92
   Botan::EC_Point uncompressed_point = grp.point(public_x, public_y);
6✔
93
   key.reset(new ECPublicKey_t(grp, uncompressed_point));
6✔
94
   return BOTAN_FFI_SUCCESS;
95
}
6✔
96

97
#endif
98

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

110
   try {
26✔
111
      return key.get_int_field(field);
64✔
112
   } catch(Botan::Unknown_PK_Field_Name&) {
2✔
113
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
2✔
114
   }
2✔
115
}
116

117
Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
35✔
118
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
119
   // Not currently handled by get_int_field
120
   if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
35✔
121
      if(field == "public_x")
20✔
122
         return ecc->public_point().get_affine_x();
2✔
123
      else if(field == "public_y")
14✔
124
         return ecc->public_point().get_affine_y();
4✔
125
   }
126
#endif
127

128
   try {
29✔
129
      return key.get_int_field(field);
60✔
130
   } catch(Botan::Unknown_PK_Field_Name&) {
4✔
131
      throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
4✔
132
   }
4✔
133
}
134

135
}  // namespace
136

137
extern "C" {
138

139
using namespace Botan_FFI;
140

141
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
142
   if(field_name_cstr == nullptr)
40✔
143
      return BOTAN_FFI_ERROR_NULL_POINTER;
144

145
   const std::string field_name(field_name_cstr);
40✔
146

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

150
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
151
   if(field_name_cstr == nullptr)
35✔
152
      return BOTAN_FFI_ERROR_NULL_POINTER;
153

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

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

159
/* RSA specific operations */
160

161
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
1✔
162
   if(n_bits < 1024 || n_bits > 16 * 1024)
1✔
163
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
164

165
   std::string n_str = std::to_string(n_bits);
1✔
166

167
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
168
}
1✔
169

170
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✔
171
#if defined(BOTAN_HAS_RSA)
172
   *key = nullptr;
2✔
173

174
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
175
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
2✔
176
      *key = new botan_privkey_struct(std::move(rsa));
2✔
177
      return BOTAN_FFI_SUCCESS;
2✔
178
   });
4✔
179
#else
180
   BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
181
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
182
#endif
183
}
184

185
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
186
#if defined(BOTAN_HAS_RSA)
187
   *key = nullptr;
1✔
188

189
   Botan::secure_vector<uint8_t> src(bits, bits + len);
1✔
190
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
191
      Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM);
1✔
192
      auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
1✔
193
      *key = new botan_privkey_struct(std::move(rsa));
1✔
194
      return BOTAN_FFI_SUCCESS;
1✔
195
   });
1✔
196
#else
197
   BOTAN_UNUSED(key, bits, len);
198
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
199
#endif
200
}
1✔
201

202
int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e) {
4✔
203
#if defined(BOTAN_HAS_RSA)
204
   *key = nullptr;
4✔
205
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
206
      auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
4✔
207
      *key = new botan_pubkey_struct(std::move(rsa));
6✔
208
      return BOTAN_FFI_SUCCESS;
3✔
209
   });
7✔
210
#else
211
   BOTAN_UNUSED(key, n, e);
212
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
213
#endif
214
}
215

216
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) { return botan_privkey_get_field(p, key, "p"); }
1✔
217

218
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) { return botan_privkey_get_field(q, key, "q"); }
1✔
219

220
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) { return botan_privkey_get_field(n, key, "n"); }
1✔
221

222
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) { return botan_privkey_get_field(e, key, "e"); }
1✔
223

224
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) { return botan_privkey_get_field(d, key, "d"); }
1✔
225

226
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) { return botan_pubkey_get_field(e, key, "e"); }
1✔
227

228
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) { return botan_pubkey_get_field(n, key, "n"); }
1✔
229

230
int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
4✔
231
#if defined(BOTAN_HAS_RSA)
232
   return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
16✔
233
      if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
234
         if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
235
            return write_vec_output(out, out_len, rsa->private_key_bits());
236
         else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
237
            return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
238
         else
239
            return BOTAN_FFI_ERROR_BAD_FLAG;
240
      } else {
241
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
242
      }
243
   });
244
#else
245
   BOTAN_UNUSED(rsa_key, out, out_len, flags);
246
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
247
#endif
248
}
249

250
/* DSA specific operations */
251
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
252
#if defined(BOTAN_HAS_DSA)
253

254
   if((rng_obj == nullptr) || (key == nullptr))
1✔
255
      return BOTAN_FFI_ERROR_NULL_POINTER;
256

257
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
258
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
259
   }
260

261
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
262
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
263
      Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
1✔
264
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
1✔
265
      *key = new botan_privkey_struct(std::move(dsa));
2✔
266
      return BOTAN_FFI_SUCCESS;
2✔
267
   });
2✔
268
#else
269
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
270
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
271
#endif
272
}
273

274
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✔
275
#if defined(BOTAN_HAS_DSA)
276
   *key = nullptr;
2✔
277

278
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
279
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
280
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
2✔
281
      *key = new botan_privkey_struct(std::move(dsa));
4✔
282
      return BOTAN_FFI_SUCCESS;
4✔
283
   });
6✔
284
#else
285
   BOTAN_UNUSED(key, p, q, g, x);
286
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
287
#endif
288
}
289

290
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✔
291
#if defined(BOTAN_HAS_DSA)
292
   *key = nullptr;
2✔
293

294
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
295
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
296
      auto dsa = std::make_unique<Botan::DSA_PublicKey>(group, safe_get(y));
2✔
297
      *key = new botan_pubkey_struct(std::move(dsa));
4✔
298
      return BOTAN_FFI_SUCCESS;
2✔
299
   });
6✔
300
#else
301
   BOTAN_UNUSED(key, p, q, g, y);
302
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
303
#endif
304
}
305

306
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) { return botan_privkey_get_field(x, key, "x"); }
2✔
307

308
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) { return botan_pubkey_get_field(p, key, "p"); }
2✔
309

310
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) { return botan_pubkey_get_field(q, key, "q"); }
2✔
311

312
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) { return botan_pubkey_get_field(g, key, "g"); }
2✔
313

314
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) { return botan_pubkey_get_field(y, key, "y"); }
2✔
315

316
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
317
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
318
}
319

320
/* ECDSA specific operations */
321

322
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
323
                            const botan_mp_t public_x,
324
                            const botan_mp_t public_y,
325
                            const char* curve_name) {
326
#if defined(BOTAN_HAS_ECDSA)
327
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
328
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
329

330
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
331
      if(rc == BOTAN_FFI_SUCCESS)
2✔
332
         *key = new botan_pubkey_struct(std::move(p_key));
4✔
333

334
      return rc;
2✔
335
   });
4✔
336
#else
337
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
338
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
339
#endif
340
}
341

342
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
343
#if defined(BOTAN_HAS_ECDSA)
344
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
345
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
2✔
346
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
2✔
347
      if(rc == BOTAN_FFI_SUCCESS)
2✔
348
         *key = new botan_privkey_struct(std::move(p_key));
4✔
349
      return rc;
2✔
350
   });
4✔
351
#else
352
   BOTAN_UNUSED(key, scalar, curve_name);
353
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
354
#endif
355
}
356

357
/* ElGamal specific operations */
358
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
359
#if defined(BOTAN_HAS_ELGAMAL)
360

361
   if((rng_obj == nullptr) || (key == nullptr))
1✔
362
      return BOTAN_FFI_ERROR_NULL_POINTER;
363

364
   if((pbits < 1024) || (qbits < 160)) {
1✔
365
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
366
   }
367

368
   Botan::DL_Group::PrimeType prime_type =
1✔
369
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
370

371
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
372
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
373
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
374
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
375
      *key = new botan_privkey_struct(std::move(elg));
2✔
376
      return BOTAN_FFI_SUCCESS;
2✔
377
   });
2✔
378
#else
379
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
380
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
381
#endif
382
}
383

384
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
2✔
385
#if defined(BOTAN_HAS_ELGAMAL)
386
   *key = nullptr;
2✔
387
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
388
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
389
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
2✔
390
      *key = new botan_pubkey_struct(std::move(elg));
4✔
391
      return BOTAN_FFI_SUCCESS;
2✔
392
   });
6✔
393
#else
394
   BOTAN_UNUSED(key, p, g, y);
395
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
396
#endif
397
}
398

399
int botan_privkey_load_elgamal(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
2✔
400
#if defined(BOTAN_HAS_ELGAMAL)
401
   *key = nullptr;
2✔
402
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
403
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
404
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(group, safe_get(x));
2✔
405
      *key = new botan_privkey_struct(std::move(elg));
4✔
406
      return BOTAN_FFI_SUCCESS;
4✔
407
   });
6✔
408
#else
409
   BOTAN_UNUSED(key, p, g, x);
410
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
411
#endif
412
}
413

414
/* Diffie Hellman specific operations */
415

416
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
417
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
418
}
419

420
int botan_privkey_load_dh(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
1✔
421
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
422
   *key = nullptr;
1✔
423
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
424
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
425
      auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
1✔
426
      *key = new botan_privkey_struct(std::move(dh));
2✔
427
      return BOTAN_FFI_SUCCESS;
2✔
428
   });
3✔
429
#else
430
   BOTAN_UNUSED(key, p, g, x);
431
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
432
#endif
433
}
434

435
int botan_pubkey_load_dh(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
1✔
436
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
437
   *key = nullptr;
1✔
438
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
439
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
440
      auto dh = std::make_unique<Botan::DH_PublicKey>(group, safe_get(y));
1✔
441
      *key = new botan_pubkey_struct(std::move(dh));
2✔
442
      return BOTAN_FFI_SUCCESS;
1✔
443
   });
3✔
444
#else
445
   BOTAN_UNUSED(key, p, g, y);
446
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
447
#endif
448
}
449

450
/* ECDH + x25519 specific operations */
451

452
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
453
   if(param_str == nullptr)
2✔
454
      return BOTAN_FFI_ERROR_NULL_POINTER;
455

456
   const std::string params(param_str);
2✔
457

458
   if(params == "curve25519")
2✔
459
      return botan_privkey_create(key_obj, "Curve25519", "", rng_obj);
×
460

461
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
462
}
2✔
463

464
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
465
                           const botan_mp_t public_x,
466
                           const botan_mp_t public_y,
467
                           const char* curve_name) {
468
#if defined(BOTAN_HAS_ECDH)
469
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
470
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
471
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
472

473
      if(rc == BOTAN_FFI_SUCCESS)
1✔
474
         *key = new botan_pubkey_struct(std::move(p_key));
2✔
475
      return rc;
1✔
476
   });
2✔
477
#else
478
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
479
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
480
#endif
481
}
482

483
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
4✔
484
#if defined(BOTAN_HAS_ECDH)
485
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
486
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
4✔
487
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
4✔
488
      if(rc == BOTAN_FFI_SUCCESS)
4✔
489
         *key = new botan_privkey_struct(std::move(p_key));
8✔
490
      return rc;
4✔
491
   });
8✔
492
#else
493
   BOTAN_UNUSED(key, scalar, curve_name);
494
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
495
#endif
496
}
497

498
/* SM2 specific operations */
499

500
int botan_pubkey_sm2_compute_za(
2✔
501
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
502
   if(out == nullptr || out_len == nullptr)
2✔
503
      return BOTAN_FFI_ERROR_NULL_POINTER;
504
   if(ident == nullptr || hash_algo == nullptr || key == nullptr)
2✔
505
      return BOTAN_FFI_ERROR_NULL_POINTER;
506

507
#if defined(BOTAN_HAS_SM2)
508
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
509
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
510
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
511

512
      if(ec_key == nullptr)
2✔
513
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
514

515
      if(ec_key->algo_name() != "SM2")
2✔
516
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
517

518
      const std::string ident_str(ident);
2✔
519
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
520

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

523
      return write_vec_output(out, out_len, za);
2✔
524
   });
6✔
525
#else
526
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
527
#endif
528
}
529

530
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
531
                          const botan_mp_t public_x,
532
                          const botan_mp_t public_y,
533
                          const char* curve_name) {
534
#if defined(BOTAN_HAS_SM2)
535
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
536
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
3✔
537
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
3✔
538
         *key = new botan_pubkey_struct(std::move(p_key));
6✔
539
         return BOTAN_FFI_SUCCESS;
3✔
540
      }
541
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
542
   });
6✔
543
#else
544
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
545
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
546
#endif
547
}
548

549
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
550
#if defined(BOTAN_HAS_SM2)
551
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
552
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
553
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
554

555
      if(rc == BOTAN_FFI_SUCCESS)
3✔
556
         *key = new botan_privkey_struct(std::move(p_key));
6✔
557
      return rc;
3✔
558
   });
6✔
559
#else
560
   BOTAN_UNUSED(key, scalar, curve_name);
561
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
562
#endif
563
}
564

565
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
566
                              const botan_mp_t public_x,
567
                              const botan_mp_t public_y,
568
                              const char* curve_name) {
569
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
570
}
571

572
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
573
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
574
}
575

576
/* Ed25519 specific operations */
577

578
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
579
#if defined(BOTAN_HAS_ED25519)
580
   *key = nullptr;
1✔
581
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
582
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
583
      auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
1✔
584
      *key = new botan_privkey_struct(std::move(ed25519));
2✔
585
      return BOTAN_FFI_SUCCESS;
2✔
586
   });
3✔
587
#else
588
   BOTAN_UNUSED(key, privkey);
589
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
590
#endif
591
}
592

593
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
594
#if defined(BOTAN_HAS_ED25519)
595
   *key = nullptr;
1✔
596
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
597
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
598
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
599
      *key = new botan_pubkey_struct(std::move(ed25519));
2✔
600
      return BOTAN_FFI_SUCCESS;
1✔
601
   });
3✔
602
#else
603
   BOTAN_UNUSED(key, pubkey);
604
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
605
#endif
606
}
607

608
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
609
#if defined(BOTAN_HAS_ED25519)
610
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
611
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
612
         const auto ed_key = ed->raw_private_key_bits();
613
         if(ed_key.size() != 64)
614
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
615
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
616
         return BOTAN_FFI_SUCCESS;
617
      } else {
618
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
619
      }
620
   });
621
#else
622
   BOTAN_UNUSED(key, output);
623
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
624
#endif
625
}
626

627
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
628
#if defined(BOTAN_HAS_ED25519)
629
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
630
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
631
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
632
         if(ed_key.size() != 32)
633
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
634
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
635
         return BOTAN_FFI_SUCCESS;
636
      } else {
637
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
638
      }
639
   });
640
#else
641
   BOTAN_UNUSED(key, output);
642
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
643
#endif
644
}
645

646
/* X25519 specific operations */
647

648
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
649
#if defined(BOTAN_HAS_X25519)
650
   *key = nullptr;
1✔
651
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
652
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
653
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
1✔
654
      *key = new botan_privkey_struct(std::move(x25519));
2✔
655
      return BOTAN_FFI_SUCCESS;
2✔
656
   });
3✔
657
#else
658
   BOTAN_UNUSED(key, privkey);
659
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
660
#endif
661
}
662

663
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
664
#if defined(BOTAN_HAS_X25519)
665
   *key = nullptr;
1✔
666
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
667
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
668
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(pubkey_vec);
1✔
669
      *key = new botan_pubkey_struct(std::move(x25519));
2✔
670
      return BOTAN_FFI_SUCCESS;
1✔
671
   });
3✔
672
#else
673
   BOTAN_UNUSED(key, pubkey);
674
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
675
#endif
676
}
677

678
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
679
#if defined(BOTAN_HAS_X25519)
680
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
681
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
682
         const auto x25519_key = x25519->raw_private_key_bits();
683
         if(x25519_key.size() != 32)
684
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
685
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
686
         return BOTAN_FFI_SUCCESS;
687
      } else {
688
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
689
      }
690
   });
691
#else
692
   BOTAN_UNUSED(key, output);
693
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
694
#endif
695
}
696

697
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
2✔
698
#if defined(BOTAN_HAS_X25519)
699
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
8✔
700
      if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
701
         const std::vector<uint8_t>& x25519_key = x25519->public_value();
702
         if(x25519_key.size() != 32)
703
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
704
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
705
         return BOTAN_FFI_SUCCESS;
706
      } else {
707
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
708
      }
709
   });
710
#else
711
   BOTAN_UNUSED(key, output);
712
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
713
#endif
714
}
715

716
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
717
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
718
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
719
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
720
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
721
         return invoke_view_callback(view, ctx, pt);
722
      } else {
723
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
724
      }
725
   });
726
#else
727
   BOTAN_UNUSED(key, view, ctx);
728
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
729
#endif
730
}
731

732
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
733
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
2✔
734
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
735
}
1✔
736

737
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
738
                         const char* aead,
739
                         const uint8_t ct[],
740
                         size_t ct_len,
741
                         const uint8_t ad[],
742
                         size_t ad_len,
743
                         uint8_t out[],
744
                         size_t* out_len) {
745
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
746
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
747
}
748

749
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
750
                         botan_rng_t rng_obj,
751
                         const char* aead,
752
                         const uint8_t pt[],
753
                         size_t pt_len,
754
                         const uint8_t ad[],
755
                         size_t ad_len,
756
                         uint8_t out[],
757
                         size_t* out_len) {
758
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
759
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
760
}
761
}
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