Botan 3.4.0
Crypto and TLS for C&
ffi_pkey_algs.cpp
Go to the documentation of this file.
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_X448)
55 #include <botan/x448.h>
56#endif
57
58#if defined(BOTAN_HAS_ED25519)
59 #include <botan/ed25519.h>
60#endif
61
62#if defined(BOTAN_HAS_ED448)
63 #include <botan/ed448.h>
64#endif
65
66#if defined(BOTAN_HAS_MCELIECE)
67 #include <botan/mceliece.h>
68#endif
69
70#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
71 #include <botan/dh.h>
72#endif
73
74#if defined(BOTAN_HAS_KYBER)
75 #include <botan/kyber.h>
76#endif
77
78namespace {
79
80#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
81
82// These are always called within an existing try/catch block
83
84template <class ECPrivateKey_t>
85int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& scalar, const char* curve_name) {
86 if(curve_name == nullptr) {
88 }
89
90 Botan::Null_RNG null_rng;
91 Botan::EC_Group grp(curve_name);
92 key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
93 return BOTAN_FFI_SUCCESS;
94}
95
96template <class ECPublicKey_t>
97int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
98 const Botan::BigInt& public_x,
99 const Botan::BigInt& public_y,
100 const char* curve_name) {
101 if(curve_name == nullptr) {
103 }
104
105 Botan::EC_Group grp(curve_name);
106 Botan::EC_Point uncompressed_point = grp.point(public_x, public_y);
107 key.reset(new ECPublicKey_t(grp, uncompressed_point));
108 return BOTAN_FFI_SUCCESS;
109}
110
111#endif
112
113Botan::BigInt pubkey_get_field(const Botan::Public_Key& key, std::string_view field) {
114#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
115 // Not currently handled by get_int_field
116 if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
117 if(field == "public_x") {
118 return ecc->public_point().get_affine_x();
119 } else if(field == "public_y") {
120 return ecc->public_point().get_affine_y();
121 }
122 }
123#endif
124
125 try {
126 return key.get_int_field(field);
128 throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
129 }
130}
131
132Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
133#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
134 // Not currently handled by get_int_field
135 if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) {
136 if(field == "public_x") {
137 return ecc->public_point().get_affine_x();
138 } else if(field == "public_y") {
139 return ecc->public_point().get_affine_y();
140 }
141 }
142#endif
143
144 try {
145 return key.get_int_field(field);
147 throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
148 }
149}
150
151} // namespace
152
153extern "C" {
154
155using namespace Botan_FFI;
156
157int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
158 if(field_name_cstr == nullptr) {
160 }
161
162 const std::string field_name(field_name_cstr);
163
164 return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
165}
166
167int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
168 if(field_name_cstr == nullptr) {
170 }
171
172 const std::string field_name(field_name_cstr);
173
174 return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
175}
176
177/* RSA specific operations */
178
179int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
180 if(n_bits < 1024 || n_bits > 16 * 1024) {
182 }
183
184 std::string n_str = std::to_string(n_bits);
185
186 return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
187}
188
190#if defined(BOTAN_HAS_RSA)
191 *key = nullptr;
192
193 return ffi_guard_thunk(__func__, [=]() -> int {
194 auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
195 *key = new botan_privkey_struct(std::move(rsa));
196 return BOTAN_FFI_SUCCESS;
197 });
198#else
199 BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
201#endif
202}
203
204int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
205#if defined(BOTAN_HAS_RSA)
206 *key = nullptr;
207
208 Botan::secure_vector<uint8_t> src(bits, bits + len);
209 return ffi_guard_thunk(__func__, [=]() -> int {
211 auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
212 *key = new botan_privkey_struct(std::move(rsa));
213 return BOTAN_FFI_SUCCESS;
214 });
215#else
216 BOTAN_UNUSED(key, bits, len);
218#endif
219}
220
222#if defined(BOTAN_HAS_RSA)
223 *key = nullptr;
224 return ffi_guard_thunk(__func__, [=]() -> int {
225 auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
226 *key = new botan_pubkey_struct(std::move(rsa));
227 return BOTAN_FFI_SUCCESS;
228 });
229#else
230 BOTAN_UNUSED(key, n, e);
232#endif
233}
234
238
242
246
250
254
256 return botan_pubkey_get_field(e, key, "e");
257}
258
260 return botan_pubkey_get_field(n, key, "n");
261}
262
263int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
264#if defined(BOTAN_HAS_RSA)
265 return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
266 if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
268 return write_vec_output(out, out_len, rsa->private_key_bits());
269 else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
270 return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), "RSA PRIVATE KEY"));
271 else
273 } else {
275 }
276 });
277#else
278 BOTAN_UNUSED(rsa_key, out, out_len, flags);
280#endif
281}
282
283/* DSA specific operations */
284int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
285#if defined(BOTAN_HAS_DSA)
286
287 if((rng_obj == nullptr) || (key == nullptr)) {
289 }
290
291 if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
293 }
294
295 return ffi_guard_thunk(__func__, [=]() -> int {
297 Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
298 auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
299 *key = new botan_privkey_struct(std::move(dsa));
300 return BOTAN_FFI_SUCCESS;
301 });
302#else
303 BOTAN_UNUSED(key, rng_obj, pbits, qbits);
305#endif
306}
307
309#if defined(BOTAN_HAS_DSA)
310 *key = nullptr;
311
312 return ffi_guard_thunk(__func__, [=]() -> int {
313 Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
314 auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
315 *key = new botan_privkey_struct(std::move(dsa));
316 return BOTAN_FFI_SUCCESS;
317 });
318#else
319 BOTAN_UNUSED(key, p, q, g, x);
321#endif
322}
323
325#if defined(BOTAN_HAS_DSA)
326 *key = nullptr;
327
328 return ffi_guard_thunk(__func__, [=]() -> int {
329 Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
330 auto dsa = std::make_unique<Botan::DSA_PublicKey>(group, safe_get(y));
331 *key = new botan_pubkey_struct(std::move(dsa));
332 return BOTAN_FFI_SUCCESS;
333 });
334#else
335 BOTAN_UNUSED(key, p, q, g, y);
337#endif
338}
339
343
345 return botan_pubkey_get_field(p, key, "p");
346}
347
349 return botan_pubkey_get_field(q, key, "q");
350}
351
353 return botan_pubkey_get_field(g, key, "g");
354}
355
357 return botan_pubkey_get_field(y, key, "y");
358}
359
360int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
361 return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
362}
363
364/* ECDSA specific operations */
365
367#if defined(BOTAN_HAS_ECC_KEY)
368 return ffi_guard_thunk(__func__, [=]() -> int {
369 const Botan::Public_Key& pub_key = safe_get(key);
370 const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
371
372 if(ec_key == nullptr) {
374 }
375
376 return ec_key->domain().used_explicit_encoding() ? 1 : 0;
377 });
378#else
379 BOTAN_UNUSED(key);
381#endif
382}
383
385 const botan_mp_t public_x,
386 const botan_mp_t public_y,
387 const char* curve_name) {
388#if defined(BOTAN_HAS_ECDSA)
389 return ffi_guard_thunk(__func__, [=]() -> int {
390 std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
391
392 int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
393 if(rc == BOTAN_FFI_SUCCESS) {
394 *key = new botan_pubkey_struct(std::move(p_key));
395 }
396
397 return rc;
398 });
399#else
400 BOTAN_UNUSED(key, public_x, public_y, curve_name);
402#endif
403}
404
405int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
406#if defined(BOTAN_HAS_ECDSA)
407 return ffi_guard_thunk(__func__, [=]() -> int {
408 std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
409 int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
410 if(rc == BOTAN_FFI_SUCCESS) {
411 *key = new botan_privkey_struct(std::move(p_key));
412 }
413 return rc;
414 });
415#else
416 BOTAN_UNUSED(key, scalar, curve_name);
418#endif
419}
420
421/* ElGamal specific operations */
422int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
423#if defined(BOTAN_HAS_ELGAMAL)
424
425 if((rng_obj == nullptr) || (key == nullptr)) {
427 }
428
429 if((pbits < 1024) || (qbits < 160)) {
431 }
432
433 Botan::DL_Group::PrimeType prime_type =
435
436 return ffi_guard_thunk(__func__, [=]() -> int {
438 Botan::DL_Group group(rng, prime_type, pbits, qbits);
439 auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
440 *key = new botan_privkey_struct(std::move(elg));
441 return BOTAN_FFI_SUCCESS;
442 });
443#else
444 BOTAN_UNUSED(key, rng_obj, pbits, qbits);
446#endif
447}
448
450#if defined(BOTAN_HAS_ELGAMAL)
451 *key = nullptr;
452 return ffi_guard_thunk(__func__, [=]() -> int {
453 Botan::DL_Group group(safe_get(p), safe_get(g));
454 auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
455 *key = new botan_pubkey_struct(std::move(elg));
456 return BOTAN_FFI_SUCCESS;
457 });
458#else
459 BOTAN_UNUSED(key, p, g, y);
461#endif
462}
463
465#if defined(BOTAN_HAS_ELGAMAL)
466 *key = nullptr;
467 return ffi_guard_thunk(__func__, [=]() -> int {
468 Botan::DL_Group group(safe_get(p), safe_get(g));
469 auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(group, safe_get(x));
470 *key = new botan_privkey_struct(std::move(elg));
471 return BOTAN_FFI_SUCCESS;
472 });
473#else
474 BOTAN_UNUSED(key, p, g, x);
476#endif
477}
478
479/* Diffie Hellman specific operations */
480
481int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
482 return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
483}
484
486#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
487 *key = nullptr;
488 return ffi_guard_thunk(__func__, [=]() -> int {
489 Botan::DL_Group group(safe_get(p), safe_get(g));
490 auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
491 *key = new botan_privkey_struct(std::move(dh));
492 return BOTAN_FFI_SUCCESS;
493 });
494#else
495 BOTAN_UNUSED(key, p, g, x);
497#endif
498}
499
501#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
502 *key = nullptr;
503 return ffi_guard_thunk(__func__, [=]() -> int {
504 Botan::DL_Group group(safe_get(p), safe_get(g));
505 auto dh = std::make_unique<Botan::DH_PublicKey>(group, safe_get(y));
506 *key = new botan_pubkey_struct(std::move(dh));
507 return BOTAN_FFI_SUCCESS;
508 });
509#else
510 BOTAN_UNUSED(key, p, g, y);
512#endif
513}
514
515/* ECDH + x25519/x448 specific operations */
516
517int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
518 if(param_str == nullptr) {
520 }
521
522 const std::string params(param_str);
523
524 if(params == "curve25519") {
525 return botan_privkey_create(key_obj, "Curve25519", "", rng_obj);
526 }
527
528 if(params == "x448") {
529 return botan_privkey_create(key_obj, "X448", "", rng_obj);
530 }
531
532 return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
533}
534
536 const botan_mp_t public_x,
537 const botan_mp_t public_y,
538 const char* curve_name) {
539#if defined(BOTAN_HAS_ECDH)
540 return ffi_guard_thunk(__func__, [=]() -> int {
541 std::unique_ptr<Botan::ECDH_PublicKey> p_key;
542 int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
543
544 if(rc == BOTAN_FFI_SUCCESS) {
545 *key = new botan_pubkey_struct(std::move(p_key));
546 }
547 return rc;
548 });
549#else
550 BOTAN_UNUSED(key, public_x, public_y, curve_name);
552#endif
553}
554
555int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
556#if defined(BOTAN_HAS_ECDH)
557 return ffi_guard_thunk(__func__, [=]() -> int {
558 std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
559 int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
560 if(rc == BOTAN_FFI_SUCCESS) {
561 *key = new botan_privkey_struct(std::move(p_key));
562 }
563 return rc;
564 });
565#else
566 BOTAN_UNUSED(key, scalar, curve_name);
568#endif
569}
570
571/* SM2 specific operations */
572
574 uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
575 if(out == nullptr || out_len == nullptr) {
577 }
578 if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
580 }
581
582#if defined(BOTAN_HAS_SM2)
583 return ffi_guard_thunk(__func__, [=]() -> int {
584 const Botan::Public_Key& pub_key = safe_get(key);
585 const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
586
587 if(ec_key == nullptr) {
589 }
590
591 if(ec_key->algo_name() != "SM2") {
593 }
594
595 const std::string ident_str(ident);
596 std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
597
598 const std::vector<uint8_t> za = Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), ec_key->public_point());
599
600 return write_vec_output(out, out_len, za);
601 });
602#else
604#endif
605}
606
608 const botan_mp_t public_x,
609 const botan_mp_t public_y,
610 const char* curve_name) {
611#if defined(BOTAN_HAS_SM2)
612 return ffi_guard_thunk(__func__, [=]() -> int {
613 std::unique_ptr<Botan::SM2_PublicKey> p_key;
614 if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
615 *key = new botan_pubkey_struct(std::move(p_key));
616 return BOTAN_FFI_SUCCESS;
617 }
619 });
620#else
621 BOTAN_UNUSED(key, public_x, public_y, curve_name);
623#endif
624}
625
626int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
627#if defined(BOTAN_HAS_SM2)
628 return ffi_guard_thunk(__func__, [=]() -> int {
629 std::unique_ptr<Botan::SM2_PrivateKey> p_key;
630 int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
631
632 if(rc == BOTAN_FFI_SUCCESS) {
633 *key = new botan_privkey_struct(std::move(p_key));
634 }
635 return rc;
636 });
637#else
638 BOTAN_UNUSED(key, scalar, curve_name);
640#endif
641}
642
644 const botan_mp_t public_x,
645 const botan_mp_t public_y,
646 const char* curve_name) {
647 return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
648}
649
650int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
651 return botan_privkey_load_sm2(key, scalar, curve_name);
652}
653
654/* Ed25519 specific operations */
655
656int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
657#if defined(BOTAN_HAS_ED25519)
658 *key = nullptr;
659 return ffi_guard_thunk(__func__, [=]() -> int {
660 const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
661 auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
662 *key = new botan_privkey_struct(std::move(ed25519));
663 return BOTAN_FFI_SUCCESS;
664 });
665#else
666 BOTAN_UNUSED(key, privkey);
668#endif
669}
670
671int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
672#if defined(BOTAN_HAS_ED25519)
673 *key = nullptr;
674 return ffi_guard_thunk(__func__, [=]() -> int {
675 const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
676 auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
677 *key = new botan_pubkey_struct(std::move(ed25519));
678 return BOTAN_FFI_SUCCESS;
679 });
680#else
681 BOTAN_UNUSED(key, pubkey);
683#endif
684}
685
687#if defined(BOTAN_HAS_ED25519)
688 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
689 if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
690 const auto ed_key = ed->raw_private_key_bits();
691 if(ed_key.size() != 64)
693 Botan::copy_mem(output, ed_key.data(), ed_key.size());
694 return BOTAN_FFI_SUCCESS;
695 } else {
697 }
698 });
699#else
700 BOTAN_UNUSED(key, output);
702#endif
703}
704
706#if defined(BOTAN_HAS_ED25519)
707 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
708 if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
709 const std::vector<uint8_t>& ed_key = ed->get_public_key();
710 if(ed_key.size() != 32)
712 Botan::copy_mem(output, ed_key.data(), ed_key.size());
713 return BOTAN_FFI_SUCCESS;
714 } else {
716 }
717 });
718#else
719 BOTAN_UNUSED(key, output);
721#endif
722}
723
724/* Ed448 specific operations */
725
726int botan_privkey_load_ed448(botan_privkey_t* key, const uint8_t privkey[57]) {
727#if defined(BOTAN_HAS_ED448)
728 *key = nullptr;
729 return ffi_guard_thunk(__func__, [=]() -> int {
730 auto ed448 = std::make_unique<Botan::Ed448_PrivateKey>(std::span(privkey, 57));
731 *key = new botan_privkey_struct(std::move(ed448));
732 return BOTAN_FFI_SUCCESS;
733 });
734#else
735 BOTAN_UNUSED(key, privkey);
737#endif
738}
739
740int botan_pubkey_load_ed448(botan_pubkey_t* key, const uint8_t pubkey[57]) {
741#if defined(BOTAN_HAS_ED448)
742 *key = nullptr;
743 return ffi_guard_thunk(__func__, [=]() -> int {
744 auto ed448 = std::make_unique<Botan::Ed448_PublicKey>(std::span(pubkey, 57));
745 *key = new botan_pubkey_struct(std::move(ed448));
746 return BOTAN_FFI_SUCCESS;
747 });
748#else
749 BOTAN_UNUSED(key, pubkey);
751#endif
752}
753
755#if defined(BOTAN_HAS_ED448)
756 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
757 if(auto ed = dynamic_cast<const Botan::Ed448_PrivateKey*>(&k)) {
758 const auto ed_key = ed->raw_private_key_bits();
759 Botan::copy_mem(std::span(output, 57), ed_key);
760 return BOTAN_FFI_SUCCESS;
761 } else {
763 }
764 });
765#else
766 BOTAN_UNUSED(key, output);
768#endif
769}
770
771int botan_pubkey_ed448_get_pubkey(botan_pubkey_t key, uint8_t output[57]) {
772#if defined(BOTAN_HAS_ED448)
773 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
774 if(auto ed = dynamic_cast<const Botan::Ed448_PublicKey*>(&k)) {
775 const auto ed_key = ed->public_key_bits();
776 Botan::copy_mem(std::span(output, 57), ed_key);
777 return BOTAN_FFI_SUCCESS;
778 } else {
780 }
781 });
782#else
783 BOTAN_UNUSED(key, output);
785#endif
786}
787
788/* X25519 specific operations */
789
790int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
791#if defined(BOTAN_HAS_X25519)
792 *key = nullptr;
793 return ffi_guard_thunk(__func__, [=]() -> int {
794 const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
795 auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
796 *key = new botan_privkey_struct(std::move(x25519));
797 return BOTAN_FFI_SUCCESS;
798 });
799#else
800 BOTAN_UNUSED(key, privkey);
802#endif
803}
804
805int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
806#if defined(BOTAN_HAS_X25519)
807 *key = nullptr;
808 return ffi_guard_thunk(__func__, [=]() -> int {
809 const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
810 auto x25519 = std::make_unique<Botan::X25519_PublicKey>(pubkey_vec);
811 *key = new botan_pubkey_struct(std::move(x25519));
812 return BOTAN_FFI_SUCCESS;
813 });
814#else
815 BOTAN_UNUSED(key, pubkey);
817#endif
818}
819
821#if defined(BOTAN_HAS_X25519)
822 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
823 if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
824 const auto x25519_key = x25519->raw_private_key_bits();
825 if(x25519_key.size() != 32)
827 Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
828 return BOTAN_FFI_SUCCESS;
829 } else {
831 }
832 });
833#else
834 BOTAN_UNUSED(key, output);
836#endif
837}
838
839int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
840#if defined(BOTAN_HAS_X25519)
841 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
842 if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
843 const std::vector<uint8_t>& x25519_key = x25519->public_value();
844 if(x25519_key.size() != 32)
846 Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
847 return BOTAN_FFI_SUCCESS;
848 } else {
850 }
851 });
852#else
853 BOTAN_UNUSED(key, output);
855#endif
856}
857
858/* X448 specific operations */
859
860int botan_privkey_load_x448(botan_privkey_t* key, const uint8_t privkey[56]) {
861#if defined(BOTAN_HAS_X448)
862 *key = nullptr;
863 return ffi_guard_thunk(__func__, [=]() -> int {
864 auto x448 = std::make_unique<Botan::X448_PrivateKey>(std::span(privkey, 56));
865 *key = new botan_privkey_struct(std::move(x448));
866 return BOTAN_FFI_SUCCESS;
867 });
868#else
869 BOTAN_UNUSED(key, privkey);
871#endif
872}
873
874int botan_pubkey_load_x448(botan_pubkey_t* key, const uint8_t pubkey[56]) {
875#if defined(BOTAN_HAS_X448)
876 *key = nullptr;
877 return ffi_guard_thunk(__func__, [=]() -> int {
878 auto x448 = std::make_unique<Botan::X448_PublicKey>(std::span(pubkey, 56));
879 *key = new botan_pubkey_struct(std::move(x448));
880 return BOTAN_FFI_SUCCESS;
881 });
882#else
883 BOTAN_UNUSED(key, pubkey);
885#endif
886}
887
889#if defined(BOTAN_HAS_X448)
890 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
891 if(auto x448 = dynamic_cast<const Botan::X448_PrivateKey*>(&k)) {
892 const auto x448_key = x448->raw_private_key_bits();
893 Botan::copy_mem(std::span(output, 56), x448_key);
894 return BOTAN_FFI_SUCCESS;
895 } else {
897 }
898 });
899#else
900 BOTAN_UNUSED(key, output);
902#endif
903}
904
905int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56]) {
906#if defined(BOTAN_HAS_X448)
907 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
908 if(auto x448 = dynamic_cast<const Botan::X448_PublicKey*>(&k)) {
909 const std::vector<uint8_t>& x448_key = x448->public_value();
910 Botan::copy_mem(std::span(output, 56), x448_key);
911 return BOTAN_FFI_SUCCESS;
912 } else {
914 }
915 });
916#else
917 BOTAN_UNUSED(key, output);
919#endif
920}
921
922/*
923* Algorithm specific key operations: Kyber
924*/
925
926int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
927#if defined(BOTAN_HAS_KYBER)
928 *key = nullptr;
929 switch(key_len) {
930 case 1632:
931 return ffi_guard_thunk(__func__, [=]() -> int {
932 const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 1632);
933 auto kyber512 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber512_R3);
934 *key = new botan_privkey_struct(std::move(kyber512));
935 return BOTAN_FFI_SUCCESS;
936 });
937 case 2400:
938 return ffi_guard_thunk(__func__, [=]() -> int {
939 const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
940 auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768_R3);
941 *key = new botan_privkey_struct(std::move(kyber768));
942 return BOTAN_FFI_SUCCESS;
943 });
944 case 3168:
945 return ffi_guard_thunk(__func__, [=]() -> int {
946 const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 3168);
947 auto kyber1024 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber1024_R3);
948 *key = new botan_privkey_struct(std::move(kyber1024));
949 return BOTAN_FFI_SUCCESS;
950 });
951 default:
952 BOTAN_UNUSED(key, privkey, key_len);
954 }
955#else
956 BOTAN_UNUSED(key, privkey);
958#endif
959}
960
961int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
962#if defined(BOTAN_HAS_KYBER)
963 *key = nullptr;
964 switch(key_len) {
965 case 800:
966 return ffi_guard_thunk(__func__, [=]() -> int {
967 const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 800);
968 auto kyber512 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber512_R3);
969 *key = new botan_pubkey_struct(std::move(kyber512));
970 return BOTAN_FFI_SUCCESS;
971 });
972 case 1184:
973 return ffi_guard_thunk(__func__, [=]() -> int {
974 const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
975 auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768_R3);
976 *key = new botan_pubkey_struct(std::move(kyber768));
977 return BOTAN_FFI_SUCCESS;
978 });
979 case 1568:
980 return ffi_guard_thunk(__func__, [=]() -> int {
981 const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1568);
982 auto kyber1024 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber1024_R3);
983 *key = new botan_pubkey_struct(std::move(kyber1024));
984 return BOTAN_FFI_SUCCESS;
985 });
986 default:
987 BOTAN_UNUSED(key, pubkey, key_len);
989 }
990#else
991 BOTAN_UNUSED(key, pubkey, key_len);
993#endif
994}
995
997#if defined(BOTAN_HAS_KYBER)
998 return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
999 if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
1000 return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
1001 } else {
1003 }
1004 });
1005#else
1006 BOTAN_UNUSED(key, ctx, view);
1008#endif
1009}
1010
1012#if defined(BOTAN_HAS_KYBER)
1013 return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
1014 if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
1015 return invoke_view_callback(view, ctx, kyber->public_key_bits());
1016 } else {
1018 }
1019 });
1020#else
1021 BOTAN_UNUSED(key, ctx, view);
1023#endif
1024}
1025
1027#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
1028 return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
1029 if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
1030 auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
1031 return invoke_view_callback(view, ctx, pt);
1032 } else {
1034 }
1035 });
1036#else
1037 BOTAN_UNUSED(key, view, ctx);
1039#endif
1040}
1041
1042int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
1043 const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
1044 return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
1045}
1046
1048 const char* aead,
1049 const uint8_t ct[],
1050 size_t ct_len,
1051 const uint8_t ad[],
1052 size_t ad_len,
1053 uint8_t out[],
1054 size_t* out_len) {
1055 BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
1057}
1058
1060 botan_rng_t rng_obj,
1061 const char* aead,
1062 const uint8_t pt[],
1063 size_t pt_len,
1064 const uint8_t ad[],
1065 size_t ad_len,
1066 uint8_t out[],
1067 size_t* out_len) {
1068 BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
1070}
1071}
#define BOTAN_UNUSED
Definition assert.h:118
virtual std::string algo_name() const =0
virtual const BigInt & get_int_field(std::string_view field) const
Definition pk_keys.cpp:18
bool used_explicit_encoding() const
Definition ec_group.h:359
const EC_Group & domain() const
Definition ecc_key.h:54
const EC_Point & public_point() const
Definition ecc_key.h:40
A private key for Ed448/Ed448ph according to RFC 8032.
Definition ed448.h:81
A public key for Ed448/Ed448ph according to RFC 8032.
Definition ed448.h:27
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:298
A private key for the X448 key agreement scheme according to RFC 7748.
Definition x448.h:65
A public key for the X448 key agreement scheme according to RFC 7748.
Definition x448.h:19
struct botan_pubkey_struct * botan_pubkey_t
Definition ffi.h:1280
struct botan_privkey_struct * botan_privkey_t
Definition ffi.h:1066
int(* botan_view_bin_fn)(botan_view_ctx view_ctx, const uint8_t *data, size_t len)
Definition ffi.h:143
int botan_privkey_create(botan_privkey_t *key, const char *algo_name, const char *algo_params, botan_rng_t rng)
Definition ffi_pkey.cpp:27
#define BOTAN_PRIVKEY_EXPORT_FLAG_PEM
Definition ffi.h:1150
struct botan_mp_struct * botan_mp_t
Definition ffi.h:869
void * botan_view_ctx
Definition ffi.h:134
struct botan_rng_struct * botan_rng_t
Definition ffi.h:260
#define BOTAN_PRIVKEY_EXPORT_FLAG_DER
Definition ffi.h:1149
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:124
@ BOTAN_FFI_ERROR_UNKNOWN_ERROR
Definition ffi.h:131
@ BOTAN_FFI_ERROR_BAD_FLAG
Definition ffi.h:117
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:118
@ BOTAN_FFI_SUCCESS
Definition ffi.h:103
@ BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE
Definition ffi.h:109
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition ffi.h:119
int botan_privkey_create_elgamal(botan_privkey_t *key, botan_rng_t rng_obj, size_t pbits, size_t qbits)
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key)
int botan_privkey_load_x448(botan_privkey_t *key, const uint8_t privkey[56])
int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char *field_name_cstr)
int botan_privkey_load_ecdh(botan_privkey_t *key, const botan_mp_t scalar, const char *curve_name)
int botan_privkey_view_kyber_raw_key(botan_privkey_t key, botan_view_ctx ctx, botan_view_bin_fn view)
int botan_pubkey_load_dh(botan_pubkey_t *key, botan_mp_t p, botan_mp_t g, botan_mp_t y)
int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, uint8_t output[32])
int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t *out_len, uint32_t flags)
int botan_privkey_load_rsa_pkcs1(botan_privkey_t *key, const uint8_t bits[], size_t len)
int botan_pubkey_load_sm2(botan_pubkey_t *key, const botan_mp_t public_x, const botan_mp_t public_y, const char *curve_name)
int botan_pubkey_sm2_compute_za(uint8_t out[], size_t *out_len, const char *ident, const char *hash_algo, const botan_pubkey_t key)
int botan_privkey_load_x25519(botan_privkey_t *key, const uint8_t privkey[32])
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key)
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key)
int botan_pubkey_ecc_key_used_explicit_encoding(botan_pubkey_t key)
int botan_privkey_ed25519_get_privkey(botan_privkey_t key, uint8_t output[64])
int botan_privkey_load_sm2_enc(botan_privkey_t *key, const botan_mp_t scalar, const char *curve_name)
int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char *field_name_cstr)
int botan_pubkey_x448_get_pubkey(botan_pubkey_t key, uint8_t output[56])
int botan_privkey_load_rsa(botan_privkey_t *key, botan_mp_t rsa_p, botan_mp_t rsa_q, botan_mp_t rsa_e)
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key)
int botan_privkey_load_ed448(botan_privkey_t *key, const uint8_t privkey[57])
int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view)
int botan_privkey_load_dh(botan_privkey_t *key, botan_mp_t p, botan_mp_t g, botan_mp_t x)
int botan_privkey_load_sm2(botan_privkey_t *key, const botan_mp_t scalar, const char *curve_name)
int botan_pubkey_load_ed25519(botan_pubkey_t *key, const uint8_t pubkey[32])
int botan_privkey_load_ecdsa(botan_privkey_t *key, const botan_mp_t scalar, const char *curve_name)
int botan_mceies_encrypt(botan_pubkey_t mce_key_obj, botan_rng_t rng_obj, const char *aead, const uint8_t pt[], size_t pt_len, const uint8_t ad[], size_t ad_len, uint8_t out[], size_t *out_len)
int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32])
int botan_pubkey_load_elgamal(botan_pubkey_t *key, botan_mp_t p, botan_mp_t g, botan_mp_t y)
int botan_privkey_create_dsa(botan_privkey_t *key, botan_rng_t rng_obj, size_t pbits, size_t qbits)
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key)
int botan_privkey_create_mceliece(botan_privkey_t *key_obj, botan_rng_t rng_obj, size_t n, size_t t)
int botan_pubkey_load_ed448(botan_pubkey_t *key, const uint8_t pubkey[57])
int botan_privkey_create_ecdh(botan_privkey_t *key_obj, botan_rng_t rng_obj, const char *param_str)
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key)
int botan_pubkey_load_sm2_enc(botan_pubkey_t *key, const botan_mp_t public_x, const botan_mp_t public_y, const char *curve_name)
int botan_mceies_decrypt(botan_privkey_t mce_key_obj, const char *aead, const uint8_t ct[], size_t ct_len, const uint8_t ad[], size_t ad_len, uint8_t out[], size_t *out_len)
int botan_pubkey_load_x25519(botan_pubkey_t *key, const uint8_t pubkey[32])
int botan_privkey_load_elgamal(botan_privkey_t *key, botan_mp_t p, botan_mp_t g, botan_mp_t x)
int botan_privkey_create_rsa(botan_privkey_t *key_obj, botan_rng_t rng_obj, size_t n_bits)
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)
int botan_pubkey_load_kyber(botan_pubkey_t *key, const uint8_t pubkey[], size_t key_len)
int botan_pubkey_ed448_get_pubkey(botan_pubkey_t key, uint8_t output[57])
int botan_privkey_create_dh(botan_privkey_t *key_obj, botan_rng_t rng_obj, const char *param_str)
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)
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key)
int botan_privkey_load_kyber(botan_privkey_t *key, const uint8_t privkey[], size_t key_len)
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key)
int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key)
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key)
int botan_pubkey_load_ecdsa(botan_pubkey_t *key, const botan_mp_t public_x, const botan_mp_t public_y, const char *curve_name)
int botan_pubkey_load_ecdh(botan_pubkey_t *key, const botan_mp_t public_x, const botan_mp_t public_y, const char *curve_name)
int botan_privkey_x448_get_privkey(botan_privkey_t key, uint8_t output[56])
int botan_privkey_load_ed25519(botan_privkey_t *key, const uint8_t privkey[32])
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key)
int botan_privkey_x25519_get_privkey(botan_privkey_t key, uint8_t output[32])
int botan_privkey_ed448_get_privkey(botan_privkey_t key, uint8_t output[57])
int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key)
int botan_pubkey_load_rsa(botan_pubkey_t *key, botan_mp_t n, botan_mp_t e)
int botan_privkey_create_ecdsa(botan_privkey_t *key_obj, botan_rng_t rng_obj, const char *param_str)
int botan_pubkey_view_kyber_raw_key(botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view)
int botan_pubkey_load_x448(botan_pubkey_t *key, const uint8_t pubkey[56])
#define BOTAN_FFI_VISIT(obj, lambda)
Definition ffi_util.h:124
std::string encode(const uint8_t der[], size_t length, std::string_view label, size_t width)
Definition pem.cpp:39
int write_str_output(uint8_t out[], size_t *out_len, std::string_view str)
Definition ffi_util.h:205
T & safe_get(botan_struct< T, M > *p)
Definition ffi_util.h:63
int invoke_view_callback(botan_view_bin_fn view, botan_view_ctx ctx, const std::vector< uint8_t, Alloc > &buf)
Definition ffi_util.h:146
int ffi_guard_thunk(const char *func_name, const std::function< int()> &thunk)
Definition ffi.cpp:116
int write_vec_output(uint8_t out[], size_t *out_len, const std::vector< uint8_t, Alloc > &buf)
Definition ffi_util.h:201
std::vector< uint8_t > sm2_compute_za(HashFunction &hash, std::string_view user_id, const EC_Group &domain, const EC_Point &pubkey)
Definition sm2.cpp:58
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:146