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

randombit / botan / 5123321399

30 May 2023 04:06PM UTC coverage: 92.213% (+0.004%) from 92.209%
5123321399

Pull #3558

github

web-flow
Merge dd72f7389 into 057bcbc35
Pull Request #3558: Add braces around all if/else statements

75602 of 81986 relevant lines covered (92.21%)

11859779.3 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

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

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

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

99
#endif
100

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

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

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

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

139
}  // namespace
140

141
extern "C" {
142

143
using namespace Botan_FFI;
144

145
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
40✔
146
   if(field_name_cstr == nullptr) {
40✔
147
      return BOTAN_FFI_ERROR_NULL_POINTER;
148
   }
149

150
   const std::string field_name(field_name_cstr);
40✔
151

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

155
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
35✔
156
   if(field_name_cstr == nullptr) {
35✔
157
      return BOTAN_FFI_ERROR_NULL_POINTER;
158
   }
159

160
   const std::string field_name(field_name_cstr);
35✔
161

162
   return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
140✔
163
}
35✔
164

165
/* RSA specific operations */
166

167
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
1✔
168
   if(n_bits < 1024 || n_bits > 16 * 1024) {
1✔
169
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
170
   }
171

172
   std::string n_str = std::to_string(n_bits);
1✔
173

174
   return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
1✔
175
}
1✔
176

177
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✔
178
#if defined(BOTAN_HAS_RSA)
179
   *key = nullptr;
2✔
180

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

192
int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
1✔
193
#if defined(BOTAN_HAS_RSA)
194
   *key = nullptr;
1✔
195

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

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

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

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

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

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

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

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

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

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

257
/* DSA specific operations */
258
int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
259
#if defined(BOTAN_HAS_DSA)
260

261
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
262
      return BOTAN_FFI_ERROR_NULL_POINTER;
263
   }
264

265
   if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
1✔
266
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
267
   }
268

269
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
270
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
271
      Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
1✔
272
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
1✔
273
      *key = new botan_privkey_struct(std::move(dsa));
2✔
274
      return BOTAN_FFI_SUCCESS;
2✔
275
   });
2✔
276
#else
277
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
278
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
279
#endif
280
}
281

282
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✔
283
#if defined(BOTAN_HAS_DSA)
284
   *key = nullptr;
2✔
285

286
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
287
      Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
2✔
288
      auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
2✔
289
      *key = new botan_privkey_struct(std::move(dsa));
4✔
290
      return BOTAN_FFI_SUCCESS;
4✔
291
   });
6✔
292
#else
293
   BOTAN_UNUSED(key, p, q, g, x);
294
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
295
#endif
296
}
297

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

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

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

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

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

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

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

324
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
1✔
325
   return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
1✔
326
}
327

328
/* ECDSA specific operations */
329

330
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
2✔
331
                            const botan_mp_t public_x,
332
                            const botan_mp_t public_y,
333
                            const char* curve_name) {
334
#if defined(BOTAN_HAS_ECDSA)
335
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
336
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
337

338
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
339
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
340
         *key = new botan_pubkey_struct(std::move(p_key));
4✔
341
      }
342

343
      return rc;
2✔
344
   });
4✔
345
#else
346
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
347
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
348
#endif
349
}
350

351
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
352
#if defined(BOTAN_HAS_ECDSA)
353
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
354
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
2✔
355
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
2✔
356
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
357
         *key = new botan_privkey_struct(std::move(p_key));
4✔
358
      }
359
      return rc;
2✔
360
   });
4✔
361
#else
362
   BOTAN_UNUSED(key, scalar, curve_name);
363
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
364
#endif
365
}
366

367
/* ElGamal specific operations */
368
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
369
#if defined(BOTAN_HAS_ELGAMAL)
370

371
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
372
      return BOTAN_FFI_ERROR_NULL_POINTER;
373
   }
374

375
   if((pbits < 1024) || (qbits < 160)) {
1✔
376
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
377
   }
378

379
   Botan::DL_Group::PrimeType prime_type =
1✔
380
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
381

382
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
383
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
384
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
385
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
386
      *key = new botan_privkey_struct(std::move(elg));
2✔
387
      return BOTAN_FFI_SUCCESS;
2✔
388
   });
2✔
389
#else
390
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
391
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
392
#endif
393
}
394

395
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
2✔
396
#if defined(BOTAN_HAS_ELGAMAL)
397
   *key = nullptr;
2✔
398
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
399
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
400
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
2✔
401
      *key = new botan_pubkey_struct(std::move(elg));
4✔
402
      return BOTAN_FFI_SUCCESS;
2✔
403
   });
6✔
404
#else
405
   BOTAN_UNUSED(key, p, g, y);
406
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
407
#endif
408
}
409

410
int botan_privkey_load_elgamal(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
2✔
411
#if defined(BOTAN_HAS_ELGAMAL)
412
   *key = nullptr;
2✔
413
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
414
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
415
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(group, safe_get(x));
2✔
416
      *key = new botan_privkey_struct(std::move(elg));
4✔
417
      return BOTAN_FFI_SUCCESS;
4✔
418
   });
6✔
419
#else
420
   BOTAN_UNUSED(key, p, g, x);
421
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
422
#endif
423
}
424

425
/* Diffie Hellman specific operations */
426

427
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
428
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
429
}
430

431
int botan_privkey_load_dh(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
1✔
432
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
433
   *key = nullptr;
1✔
434
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
435
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
436
      auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
1✔
437
      *key = new botan_privkey_struct(std::move(dh));
2✔
438
      return BOTAN_FFI_SUCCESS;
2✔
439
   });
3✔
440
#else
441
   BOTAN_UNUSED(key, p, g, x);
442
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
443
#endif
444
}
445

446
int botan_pubkey_load_dh(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
1✔
447
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
448
   *key = nullptr;
1✔
449
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
450
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
451
      auto dh = std::make_unique<Botan::DH_PublicKey>(group, safe_get(y));
1✔
452
      *key = new botan_pubkey_struct(std::move(dh));
2✔
453
      return BOTAN_FFI_SUCCESS;
1✔
454
   });
3✔
455
#else
456
   BOTAN_UNUSED(key, p, g, y);
457
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
458
#endif
459
}
460

461
/* ECDH + x25519 specific operations */
462

463
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
464
   if(param_str == nullptr) {
2✔
465
      return BOTAN_FFI_ERROR_NULL_POINTER;
466
   }
467

468
   const std::string params(param_str);
2✔
469

470
   if(params == "curve25519") {
2✔
471
      return botan_privkey_create(key_obj, "Curve25519", "", rng_obj);
×
472
   }
473

474
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
475
}
2✔
476

477
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
478
                           const botan_mp_t public_x,
479
                           const botan_mp_t public_y,
480
                           const char* curve_name) {
481
#if defined(BOTAN_HAS_ECDH)
482
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
483
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
484
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
485

486
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
487
         *key = new botan_pubkey_struct(std::move(p_key));
2✔
488
      }
489
      return rc;
1✔
490
   });
2✔
491
#else
492
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
493
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
494
#endif
495
}
496

497
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
4✔
498
#if defined(BOTAN_HAS_ECDH)
499
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
500
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
4✔
501
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
4✔
502
      if(rc == BOTAN_FFI_SUCCESS) {
4✔
503
         *key = new botan_privkey_struct(std::move(p_key));
8✔
504
      }
505
      return rc;
4✔
506
   });
8✔
507
#else
508
   BOTAN_UNUSED(key, scalar, curve_name);
509
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
510
#endif
511
}
512

513
/* SM2 specific operations */
514

515
int botan_pubkey_sm2_compute_za(
2✔
516
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
517
   if(out == nullptr || out_len == nullptr) {
2✔
518
      return BOTAN_FFI_ERROR_NULL_POINTER;
519
   }
520
   if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
521
      return BOTAN_FFI_ERROR_NULL_POINTER;
522
   }
523

524
#if defined(BOTAN_HAS_SM2)
525
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
526
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
527
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
528

529
      if(ec_key == nullptr) {
2✔
530
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
531
      }
532

533
      if(ec_key->algo_name() != "SM2") {
2✔
534
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
535
      }
536

537
      const std::string ident_str(ident);
2✔
538
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
539

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

542
      return write_vec_output(out, out_len, za);
2✔
543
   });
6✔
544
#else
545
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
546
#endif
547
}
548

549
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
550
                          const botan_mp_t public_x,
551
                          const botan_mp_t public_y,
552
                          const char* curve_name) {
553
#if defined(BOTAN_HAS_SM2)
554
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
555
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
3✔
556
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
3✔
557
         *key = new botan_pubkey_struct(std::move(p_key));
6✔
558
         return BOTAN_FFI_SUCCESS;
3✔
559
      }
560
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
561
   });
6✔
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_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
569
#if defined(BOTAN_HAS_SM2)
570
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
571
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
572
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
573

574
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
575
         *key = new botan_privkey_struct(std::move(p_key));
6✔
576
      }
577
      return rc;
3✔
578
   });
6✔
579
#else
580
   BOTAN_UNUSED(key, scalar, curve_name);
581
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
582
#endif
583
}
584

585
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
586
                              const botan_mp_t public_x,
587
                              const botan_mp_t public_y,
588
                              const char* curve_name) {
589
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
590
}
591

592
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
593
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
594
}
595

596
/* Ed25519 specific operations */
597

598
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
599
#if defined(BOTAN_HAS_ED25519)
600
   *key = nullptr;
1✔
601
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
602
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
603
      auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
1✔
604
      *key = new botan_privkey_struct(std::move(ed25519));
2✔
605
      return BOTAN_FFI_SUCCESS;
2✔
606
   });
3✔
607
#else
608
   BOTAN_UNUSED(key, privkey);
609
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
610
#endif
611
}
612

613
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
614
#if defined(BOTAN_HAS_ED25519)
615
   *key = nullptr;
1✔
616
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
617
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
618
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
619
      *key = new botan_pubkey_struct(std::move(ed25519));
2✔
620
      return BOTAN_FFI_SUCCESS;
1✔
621
   });
3✔
622
#else
623
   BOTAN_UNUSED(key, pubkey);
624
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
625
#endif
626
}
627

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

647
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
1✔
648
#if defined(BOTAN_HAS_ED25519)
649
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
2✔
650
      if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
651
         const std::vector<uint8_t>& ed_key = ed->get_public_key();
652
         if(ed_key.size() != 32)
653
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
654
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
655
         return BOTAN_FFI_SUCCESS;
656
      } else {
657
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
658
      }
659
   });
660
#else
661
   BOTAN_UNUSED(key, output);
662
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
663
#endif
664
}
665

666
/* X25519 specific operations */
667

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

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

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

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

736
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
737
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
738
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
739
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
740
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
741
         return invoke_view_callback(view, ctx, pt);
742
      } else {
743
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
744
      }
745
   });
746
#else
747
   BOTAN_UNUSED(key, view, ctx);
748
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
749
#endif
750
}
751

752
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
753
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
2✔
754
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
755
}
1✔
756

757
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
758
                         const char* aead,
759
                         const uint8_t ct[],
760
                         size_t ct_len,
761
                         const uint8_t ad[],
762
                         size_t ad_len,
763
                         uint8_t out[],
764
                         size_t* out_len) {
765
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
766
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
767
}
768

769
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
770
                         botan_rng_t rng_obj,
771
                         const char* aead,
772
                         const uint8_t pt[],
773
                         size_t pt_len,
774
                         const uint8_t ad[],
775
                         size_t ad_len,
776
                         uint8_t out[],
777
                         size_t* out_len) {
778
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
779
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
780
}
781
}
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