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

randombit / botan / 5230455705

10 Jun 2023 02:30PM UTC coverage: 91.715% (-0.03%) from 91.746%
5230455705

push

github

randombit
Merge GH #3584 Change clang-format AllowShortFunctionsOnASingleLine config from All to Inline

77182 of 84154 relevant lines covered (91.72%)

11975295.43 hits per line

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

97.99
/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_load_ecdsa(botan_pubkey_t* key,
2✔
359
                            const botan_mp_t public_x,
360
                            const botan_mp_t public_y,
361
                            const char* curve_name) {
362
#if defined(BOTAN_HAS_ECDSA)
363
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
364
      std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
2✔
365

366
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
2✔
367
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
368
         *key = new botan_pubkey_struct(std::move(p_key));
4✔
369
      }
370

371
      return rc;
2✔
372
   });
4✔
373
#else
374
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
375
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
376
#endif
377
}
378

379
int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
2✔
380
#if defined(BOTAN_HAS_ECDSA)
381
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
382
      std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
2✔
383
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
2✔
384
      if(rc == BOTAN_FFI_SUCCESS) {
2✔
385
         *key = new botan_privkey_struct(std::move(p_key));
4✔
386
      }
387
      return rc;
2✔
388
   });
4✔
389
#else
390
   BOTAN_UNUSED(key, scalar, curve_name);
391
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
392
#endif
393
}
394

395
/* ElGamal specific operations */
396
int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
1✔
397
#if defined(BOTAN_HAS_ELGAMAL)
398

399
   if((rng_obj == nullptr) || (key == nullptr)) {
1✔
400
      return BOTAN_FFI_ERROR_NULL_POINTER;
401
   }
402

403
   if((pbits < 1024) || (qbits < 160)) {
1✔
404
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
405
   }
406

407
   Botan::DL_Group::PrimeType prime_type =
1✔
408
      ((pbits - 1) == qbits) ? Botan::DL_Group::Strong : Botan::DL_Group::Prime_Subgroup;
1✔
409

410
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
411
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
1✔
412
      Botan::DL_Group group(rng, prime_type, pbits, qbits);
1✔
413
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
1✔
414
      *key = new botan_privkey_struct(std::move(elg));
2✔
415
      return BOTAN_FFI_SUCCESS;
2✔
416
   });
2✔
417
#else
418
   BOTAN_UNUSED(key, rng_obj, pbits, qbits);
419
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
420
#endif
421
}
422

423
int botan_pubkey_load_elgamal(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
2✔
424
#if defined(BOTAN_HAS_ELGAMAL)
425
   *key = nullptr;
2✔
426
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
427
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
428
      auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
2✔
429
      *key = new botan_pubkey_struct(std::move(elg));
4✔
430
      return BOTAN_FFI_SUCCESS;
2✔
431
   });
6✔
432
#else
433
   BOTAN_UNUSED(key, p, g, y);
434
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
435
#endif
436
}
437

438
int botan_privkey_load_elgamal(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
2✔
439
#if defined(BOTAN_HAS_ELGAMAL)
440
   *key = nullptr;
2✔
441
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
442
      Botan::DL_Group group(safe_get(p), safe_get(g));
2✔
443
      auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(group, safe_get(x));
2✔
444
      *key = new botan_privkey_struct(std::move(elg));
4✔
445
      return BOTAN_FFI_SUCCESS;
4✔
446
   });
6✔
447
#else
448
   BOTAN_UNUSED(key, p, g, x);
449
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
450
#endif
451
}
452

453
/* Diffie Hellman specific operations */
454

455
int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
456
   return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
2✔
457
}
458

459
int botan_privkey_load_dh(botan_privkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t x) {
1✔
460
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
461
   *key = nullptr;
1✔
462
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
463
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
464
      auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
1✔
465
      *key = new botan_privkey_struct(std::move(dh));
2✔
466
      return BOTAN_FFI_SUCCESS;
2✔
467
   });
3✔
468
#else
469
   BOTAN_UNUSED(key, p, g, x);
470
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
471
#endif
472
}
473

474
int botan_pubkey_load_dh(botan_pubkey_t* key, botan_mp_t p, botan_mp_t g, botan_mp_t y) {
1✔
475
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
476
   *key = nullptr;
1✔
477
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
478
      Botan::DL_Group group(safe_get(p), safe_get(g));
1✔
479
      auto dh = std::make_unique<Botan::DH_PublicKey>(group, safe_get(y));
1✔
480
      *key = new botan_pubkey_struct(std::move(dh));
2✔
481
      return BOTAN_FFI_SUCCESS;
1✔
482
   });
3✔
483
#else
484
   BOTAN_UNUSED(key, p, g, y);
485
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
486
#endif
487
}
488

489
/* ECDH + x25519 specific operations */
490

491
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
2✔
492
   if(param_str == nullptr) {
2✔
493
      return BOTAN_FFI_ERROR_NULL_POINTER;
494
   }
495

496
   const std::string params(param_str);
2✔
497

498
   if(params == "curve25519") {
2✔
499
      return botan_privkey_create(key_obj, "Curve25519", "", rng_obj);
×
500
   }
501

502
   return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
2✔
503
}
2✔
504

505
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
1✔
506
                           const botan_mp_t public_x,
507
                           const botan_mp_t public_y,
508
                           const char* curve_name) {
509
#if defined(BOTAN_HAS_ECDH)
510
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
511
      std::unique_ptr<Botan::ECDH_PublicKey> p_key;
1✔
512
      int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
1✔
513

514
      if(rc == BOTAN_FFI_SUCCESS) {
1✔
515
         *key = new botan_pubkey_struct(std::move(p_key));
2✔
516
      }
517
      return rc;
1✔
518
   });
2✔
519
#else
520
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
521
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
522
#endif
523
}
524

525
int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
4✔
526
#if defined(BOTAN_HAS_ECDH)
527
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
528
      std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
4✔
529
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
4✔
530
      if(rc == BOTAN_FFI_SUCCESS) {
4✔
531
         *key = new botan_privkey_struct(std::move(p_key));
8✔
532
      }
533
      return rc;
4✔
534
   });
8✔
535
#else
536
   BOTAN_UNUSED(key, scalar, curve_name);
537
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
538
#endif
539
}
540

541
/* SM2 specific operations */
542

543
int botan_pubkey_sm2_compute_za(
2✔
544
   uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
545
   if(out == nullptr || out_len == nullptr) {
2✔
546
      return BOTAN_FFI_ERROR_NULL_POINTER;
547
   }
548
   if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
2✔
549
      return BOTAN_FFI_ERROR_NULL_POINTER;
550
   }
551

552
#if defined(BOTAN_HAS_SM2)
553
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
554
      const Botan::Public_Key& pub_key = safe_get(key);
2✔
555
      const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
2✔
556

557
      if(ec_key == nullptr) {
2✔
558
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
559
      }
560

561
      if(ec_key->algo_name() != "SM2") {
2✔
562
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
563
      }
564

565
      const std::string ident_str(ident);
2✔
566
      std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
2✔
567

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

570
      return write_vec_output(out, out_len, za);
2✔
571
   });
6✔
572
#else
573
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
574
#endif
575
}
576

577
int botan_pubkey_load_sm2(botan_pubkey_t* key,
3✔
578
                          const botan_mp_t public_x,
579
                          const botan_mp_t public_y,
580
                          const char* curve_name) {
581
#if defined(BOTAN_HAS_SM2)
582
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
583
      std::unique_ptr<Botan::SM2_PublicKey> p_key;
3✔
584
      if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
3✔
585
         *key = new botan_pubkey_struct(std::move(p_key));
6✔
586
         return BOTAN_FFI_SUCCESS;
3✔
587
      }
588
      return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
589
   });
6✔
590
#else
591
   BOTAN_UNUSED(key, public_x, public_y, curve_name);
592
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
593
#endif
594
}
595

596
int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
3✔
597
#if defined(BOTAN_HAS_SM2)
598
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
599
      std::unique_ptr<Botan::SM2_PrivateKey> p_key;
3✔
600
      int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
3✔
601

602
      if(rc == BOTAN_FFI_SUCCESS) {
3✔
603
         *key = new botan_privkey_struct(std::move(p_key));
6✔
604
      }
605
      return rc;
3✔
606
   });
6✔
607
#else
608
   BOTAN_UNUSED(key, scalar, curve_name);
609
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
610
#endif
611
}
612

613
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
1✔
614
                              const botan_mp_t public_x,
615
                              const botan_mp_t public_y,
616
                              const char* curve_name) {
617
   return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
1✔
618
}
619

620
int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
1✔
621
   return botan_privkey_load_sm2(key, scalar, curve_name);
1✔
622
}
623

624
/* Ed25519 specific operations */
625

626
int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
627
#if defined(BOTAN_HAS_ED25519)
628
   *key = nullptr;
1✔
629
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
630
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
631
      auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
1✔
632
      *key = new botan_privkey_struct(std::move(ed25519));
2✔
633
      return BOTAN_FFI_SUCCESS;
2✔
634
   });
3✔
635
#else
636
   BOTAN_UNUSED(key, privkey);
637
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
638
#endif
639
}
640

641
int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
642
#if defined(BOTAN_HAS_ED25519)
643
   *key = nullptr;
1✔
644
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
645
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
646
      auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
1✔
647
      *key = new botan_pubkey_struct(std::move(ed25519));
2✔
648
      return BOTAN_FFI_SUCCESS;
1✔
649
   });
3✔
650
#else
651
   BOTAN_UNUSED(key, pubkey);
652
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
653
#endif
654
}
655

656
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64]) {
1✔
657
#if defined(BOTAN_HAS_ED25519)
658
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
659
      if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
660
         const auto ed_key = ed->raw_private_key_bits();
661
         if(ed_key.size() != 64)
662
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
663
         Botan::copy_mem(output, ed_key.data(), ed_key.size());
664
         return BOTAN_FFI_SUCCESS;
665
      } else {
666
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
667
      }
668
   });
669
#else
670
   BOTAN_UNUSED(key, output);
671
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
672
#endif
673
}
674

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

694
/* X25519 specific operations */
695

696
int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
1✔
697
#if defined(BOTAN_HAS_X25519)
698
   *key = nullptr;
1✔
699
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
700
      const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
1✔
701
      auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
1✔
702
      *key = new botan_privkey_struct(std::move(x25519));
2✔
703
      return BOTAN_FFI_SUCCESS;
2✔
704
   });
3✔
705
#else
706
   BOTAN_UNUSED(key, privkey);
707
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
708
#endif
709
}
710

711
int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
1✔
712
#if defined(BOTAN_HAS_X25519)
713
   *key = nullptr;
1✔
714
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
715
      const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
1✔
716
      auto x25519 = std::make_unique<Botan::X25519_PublicKey>(pubkey_vec);
1✔
717
      *key = new botan_pubkey_struct(std::move(x25519));
2✔
718
      return BOTAN_FFI_SUCCESS;
1✔
719
   });
3✔
720
#else
721
   BOTAN_UNUSED(key, pubkey);
722
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
723
#endif
724
}
725

726
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32]) {
1✔
727
#if defined(BOTAN_HAS_X25519)
728
   return BOTAN_FFI_VISIT(key, [=](const auto& k) {
4✔
729
      if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
730
         const auto x25519_key = x25519->raw_private_key_bits();
731
         if(x25519_key.size() != 32)
732
            return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
733
         Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
734
         return BOTAN_FFI_SUCCESS;
735
      } else {
736
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
737
      }
738
   });
739
#else
740
   BOTAN_UNUSED(key, output);
741
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
742
#endif
743
}
744

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

764
/*
765
* Algorithm specific key operations: Kyber
766
*/
767

768
int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
4✔
769
#if defined(BOTAN_HAS_KYBER)
770
   *key = nullptr;
4✔
771
   switch(key_len) {
4✔
772
      case 1632:
1✔
773
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
774
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 1632);
1✔
775
            auto kyber512 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber512);
1✔
776
            *key = new botan_privkey_struct(std::move(kyber512));
1✔
777
            return BOTAN_FFI_SUCCESS;
2✔
778
         });
2✔
779
      case 2400:
2✔
780
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
781
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
2✔
782
            auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768);
2✔
783
            *key = new botan_privkey_struct(std::move(kyber768));
2✔
784
            return BOTAN_FFI_SUCCESS;
4✔
785
         });
4✔
786
      case 3168:
1✔
787
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
788
            const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 3168);
1✔
789
            auto kyber1024 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber1024);
1✔
790
            *key = new botan_privkey_struct(std::move(kyber1024));
1✔
791
            return BOTAN_FFI_SUCCESS;
2✔
792
         });
2✔
793
      default:
794
         BOTAN_UNUSED(key, privkey, key_len);
795
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
796
   }
797
#else
798
   BOTAN_UNUSED(key, privkey);
799
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
800
#endif
801
}
802

803
int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
4✔
804
#if defined(BOTAN_HAS_KYBER)
805
   *key = nullptr;
4✔
806
   switch(key_len) {
4✔
807
      case 800:
1✔
808
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
809
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 800);
1✔
810
            auto kyber512 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber512);
1✔
811
            *key = new botan_pubkey_struct(std::move(kyber512));
2✔
812
            return BOTAN_FFI_SUCCESS;
1✔
813
         });
2✔
814
      case 1184:
2✔
815
         return ffi_guard_thunk(__func__, [=]() -> int {
4✔
816
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
2✔
817
            auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768);
2✔
818
            *key = new botan_pubkey_struct(std::move(kyber768));
4✔
819
            return BOTAN_FFI_SUCCESS;
2✔
820
         });
4✔
821
      case 1568:
1✔
822
         return ffi_guard_thunk(__func__, [=]() -> int {
2✔
823
            const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1568);
1✔
824
            auto kyber1024 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber1024);
1✔
825
            *key = new botan_pubkey_struct(std::move(kyber1024));
2✔
826
            return BOTAN_FFI_SUCCESS;
1✔
827
         });
2✔
828
      default:
829
         BOTAN_UNUSED(key, pubkey, key_len);
830
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
831
   }
832
#else
833
   BOTAN_UNUSED(key, pubkey, key_len);
834
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
835
#endif
836
}
837

838
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
4✔
839
#if defined(BOTAN_HAS_KYBER)
840
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
12✔
841
      if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
842
         return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
843
      } else {
844
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
845
      }
846
   });
847
#else
848
   BOTAN_UNUSED(key, ctx, view);
849
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
850
#endif
851
}
852

853
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
8✔
854
#if defined(BOTAN_HAS_KYBER)
855
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
24✔
856
      if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
857
         return invoke_view_callback(view, ctx, kyber->public_key_bits());
858
      } else {
859
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
860
      }
861
   });
862
#else
863
   BOTAN_UNUSED(key, ctx, view);
864
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
865
#endif
866
}
867

868
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
6✔
869
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
870
   return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
18✔
871
      if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
872
         auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
873
         return invoke_view_callback(view, ctx, pt);
874
      } else {
875
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
876
      }
877
   });
878
#else
879
   BOTAN_UNUSED(key, view, ctx);
880
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
881
#endif
882
}
883

884
int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1✔
885
   const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
2✔
886
   return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1✔
887
}
1✔
888

889
int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
×
890
                         const char* aead,
891
                         const uint8_t ct[],
892
                         size_t ct_len,
893
                         const uint8_t ad[],
894
                         size_t ad_len,
895
                         uint8_t out[],
896
                         size_t* out_len) {
897
   BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
×
898
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
899
}
900

901
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
×
902
                         botan_rng_t rng_obj,
903
                         const char* aead,
904
                         const uint8_t pt[],
905
                         size_t pt_len,
906
                         const uint8_t ad[],
907
                         size_t ad_len,
908
                         uint8_t out[],
909
                         size_t* out_len) {
910
   BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
×
911
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
×
912
}
913
}
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

© 2025 Coveralls, Inc