Botan 3.3.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_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
70namespace {
71
72#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
73
74// These are always called within an existing try/catch block
75
76template <class ECPrivateKey_t>
77int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& scalar, const char* curve_name) {
78 if(curve_name == nullptr) {
80 }
81
82 Botan::Null_RNG null_rng;
83 Botan::EC_Group grp(curve_name);
84 key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
85 return BOTAN_FFI_SUCCESS;
86}
87
88template <class ECPublicKey_t>
89int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
90 const Botan::BigInt& public_x,
91 const Botan::BigInt& public_y,
92 const char* curve_name) {
93 if(curve_name == nullptr) {
95 }
96
97 Botan::EC_Group grp(curve_name);
98 Botan::EC_Point uncompressed_point = grp.point(public_x, public_y);
99 key.reset(new ECPublicKey_t(grp, uncompressed_point));
100 return BOTAN_FFI_SUCCESS;
101}
102
103#endif
104
105Botan::BigInt pubkey_get_field(const Botan::Public_Key& key, std::string_view field) {
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)) {
109 if(field == "public_x") {
110 return ecc->public_point().get_affine_x();
111 } else if(field == "public_y") {
112 return ecc->public_point().get_affine_y();
113 }
114 }
115#endif
116
117 try {
118 return key.get_int_field(field);
120 throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
121 }
122}
123
124Botan::BigInt privkey_get_field(const Botan::Private_Key& key, std::string_view field) {
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)) {
128 if(field == "public_x") {
129 return ecc->public_point().get_affine_x();
130 } else if(field == "public_y") {
131 return ecc->public_point().get_affine_y();
132 }
133 }
134#endif
135
136 try {
137 return key.get_int_field(field);
139 throw Botan_FFI::FFI_Error("Unknown key field", BOTAN_FFI_ERROR_BAD_PARAMETER);
140 }
141}
142
143} // namespace
144
145extern "C" {
146
147using namespace Botan_FFI;
148
149int botan_pubkey_get_field(botan_mp_t output, botan_pubkey_t key, const char* field_name_cstr) {
150 if(field_name_cstr == nullptr) {
152 }
153
154 const std::string field_name(field_name_cstr);
155
156 return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = pubkey_get_field(k, field_name); });
157}
158
159int botan_privkey_get_field(botan_mp_t output, botan_privkey_t key, const char* field_name_cstr) {
160 if(field_name_cstr == nullptr) {
162 }
163
164 const std::string field_name(field_name_cstr);
165
166 return BOTAN_FFI_VISIT(key, [=](const auto& k) { safe_get(output) = privkey_get_field(k, field_name); });
167}
168
169/* RSA specific operations */
170
171int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) {
172 if(n_bits < 1024 || n_bits > 16 * 1024) {
174 }
175
176 std::string n_str = std::to_string(n_bits);
177
178 return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj);
179}
180
182#if defined(BOTAN_HAS_RSA)
183 *key = nullptr;
184
185 return ffi_guard_thunk(__func__, [=]() -> int {
186 auto rsa = std::make_unique<Botan::RSA_PrivateKey>(safe_get(rsa_p), safe_get(rsa_q), safe_get(rsa_e));
187 *key = new botan_privkey_struct(std::move(rsa));
188 return BOTAN_FFI_SUCCESS;
189 });
190#else
191 BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e);
193#endif
194}
195
196int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, const uint8_t bits[], size_t len) {
197#if defined(BOTAN_HAS_RSA)
198 *key = nullptr;
199
200 Botan::secure_vector<uint8_t> src(bits, bits + len);
201 return ffi_guard_thunk(__func__, [=]() -> int {
203 auto rsa = std::make_unique<Botan::RSA_PrivateKey>(alg_id, src);
204 *key = new botan_privkey_struct(std::move(rsa));
205 return BOTAN_FFI_SUCCESS;
206 });
207#else
208 BOTAN_UNUSED(key, bits, len);
210#endif
211}
212
214#if defined(BOTAN_HAS_RSA)
215 *key = nullptr;
216 return ffi_guard_thunk(__func__, [=]() -> int {
217 auto rsa = std::make_unique<Botan::RSA_PublicKey>(safe_get(n), safe_get(e));
218 *key = new botan_pubkey_struct(std::move(rsa));
219 return BOTAN_FFI_SUCCESS;
220 });
221#else
222 BOTAN_UNUSED(key, n, e);
224#endif
225}
226
230
234
238
242
246
248 return botan_pubkey_get_field(e, key, "e");
249}
250
252 return botan_pubkey_get_field(n, key, "n");
253}
254
255int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, uint8_t out[], size_t* out_len, uint32_t flags) {
256#if defined(BOTAN_HAS_RSA)
257 return BOTAN_FFI_VISIT(rsa_key, [=](const auto& k) -> int {
258 if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) {
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
265 } else {
267 }
268 });
269#else
270 BOTAN_UNUSED(rsa_key, out, out_len, flags);
272#endif
273}
274
275/* DSA specific operations */
276int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
277#if defined(BOTAN_HAS_DSA)
278
279 if((rng_obj == nullptr) || (key == nullptr)) {
281 }
282
283 if((pbits % 64) || (qbits % 8) || (pbits < 1024) || (pbits > 3072) || (qbits < 160) || (qbits > 256)) {
285 }
286
287 return ffi_guard_thunk(__func__, [=]() -> int {
289 Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits);
290 auto dsa = std::make_unique<Botan::DSA_PrivateKey>(rng, group);
291 *key = new botan_privkey_struct(std::move(dsa));
292 return BOTAN_FFI_SUCCESS;
293 });
294#else
295 BOTAN_UNUSED(key, rng_obj, pbits, qbits);
297#endif
298}
299
301#if defined(BOTAN_HAS_DSA)
302 *key = nullptr;
303
304 return ffi_guard_thunk(__func__, [=]() -> int {
305 Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
306 auto dsa = std::make_unique<Botan::DSA_PrivateKey>(group, safe_get(x));
307 *key = new botan_privkey_struct(std::move(dsa));
308 return BOTAN_FFI_SUCCESS;
309 });
310#else
311 BOTAN_UNUSED(key, p, q, g, x);
313#endif
314}
315
317#if defined(BOTAN_HAS_DSA)
318 *key = nullptr;
319
320 return ffi_guard_thunk(__func__, [=]() -> int {
321 Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
322 auto dsa = std::make_unique<Botan::DSA_PublicKey>(group, safe_get(y));
323 *key = new botan_pubkey_struct(std::move(dsa));
324 return BOTAN_FFI_SUCCESS;
325 });
326#else
327 BOTAN_UNUSED(key, p, q, g, y);
329#endif
330}
331
335
337 return botan_pubkey_get_field(p, key, "p");
338}
339
341 return botan_pubkey_get_field(q, key, "q");
342}
343
345 return botan_pubkey_get_field(g, key, "g");
346}
347
349 return botan_pubkey_get_field(y, key, "y");
350}
351
352int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
353 return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj);
354}
355
356/* ECDSA specific operations */
357
359#if defined(BOTAN_HAS_ECC_KEY)
360 return ffi_guard_thunk(__func__, [=]() -> int {
361 const Botan::Public_Key& pub_key = safe_get(key);
362 const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
363
364 if(ec_key == nullptr) {
366 }
367
368 return ec_key->domain().used_explicit_encoding() ? 1 : 0;
369 });
370#else
371 BOTAN_UNUSED(key);
373#endif
374}
375
377 const botan_mp_t public_x,
378 const botan_mp_t public_y,
379 const char* curve_name) {
380#if defined(BOTAN_HAS_ECDSA)
381 return ffi_guard_thunk(__func__, [=]() -> int {
382 std::unique_ptr<Botan::ECDSA_PublicKey> p_key;
383
384 int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
385 if(rc == BOTAN_FFI_SUCCESS) {
386 *key = new botan_pubkey_struct(std::move(p_key));
387 }
388
389 return rc;
390 });
391#else
392 BOTAN_UNUSED(key, public_x, public_y, curve_name);
394#endif
395}
396
397int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
398#if defined(BOTAN_HAS_ECDSA)
399 return ffi_guard_thunk(__func__, [=]() -> int {
400 std::unique_ptr<Botan::ECDSA_PrivateKey> p_key;
401 int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
402 if(rc == BOTAN_FFI_SUCCESS) {
403 *key = new botan_privkey_struct(std::move(p_key));
404 }
405 return rc;
406 });
407#else
408 BOTAN_UNUSED(key, scalar, curve_name);
410#endif
411}
412
413/* ElGamal specific operations */
414int botan_privkey_create_elgamal(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) {
415#if defined(BOTAN_HAS_ELGAMAL)
416
417 if((rng_obj == nullptr) || (key == nullptr)) {
419 }
420
421 if((pbits < 1024) || (qbits < 160)) {
423 }
424
425 Botan::DL_Group::PrimeType prime_type =
427
428 return ffi_guard_thunk(__func__, [=]() -> int {
430 Botan::DL_Group group(rng, prime_type, pbits, qbits);
431 auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(rng, group);
432 *key = new botan_privkey_struct(std::move(elg));
433 return BOTAN_FFI_SUCCESS;
434 });
435#else
436 BOTAN_UNUSED(key, rng_obj, pbits, qbits);
438#endif
439}
440
442#if defined(BOTAN_HAS_ELGAMAL)
443 *key = nullptr;
444 return ffi_guard_thunk(__func__, [=]() -> int {
445 Botan::DL_Group group(safe_get(p), safe_get(g));
446 auto elg = std::make_unique<Botan::ElGamal_PublicKey>(group, safe_get(y));
447 *key = new botan_pubkey_struct(std::move(elg));
448 return BOTAN_FFI_SUCCESS;
449 });
450#else
451 BOTAN_UNUSED(key, p, g, y);
453#endif
454}
455
457#if defined(BOTAN_HAS_ELGAMAL)
458 *key = nullptr;
459 return ffi_guard_thunk(__func__, [=]() -> int {
460 Botan::DL_Group group(safe_get(p), safe_get(g));
461 auto elg = std::make_unique<Botan::ElGamal_PrivateKey>(group, safe_get(x));
462 *key = new botan_privkey_struct(std::move(elg));
463 return BOTAN_FFI_SUCCESS;
464 });
465#else
466 BOTAN_UNUSED(key, p, g, x);
468#endif
469}
470
471/* Diffie Hellman specific operations */
472
473int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
474 return botan_privkey_create(key_obj, "DH", param_str, rng_obj);
475}
476
478#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
479 *key = nullptr;
480 return ffi_guard_thunk(__func__, [=]() -> int {
481 Botan::DL_Group group(safe_get(p), safe_get(g));
482 auto dh = std::make_unique<Botan::DH_PrivateKey>(group, safe_get(x));
483 *key = new botan_privkey_struct(std::move(dh));
484 return BOTAN_FFI_SUCCESS;
485 });
486#else
487 BOTAN_UNUSED(key, p, g, x);
489#endif
490}
491
493#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
494 *key = nullptr;
495 return ffi_guard_thunk(__func__, [=]() -> int {
496 Botan::DL_Group group(safe_get(p), safe_get(g));
497 auto dh = std::make_unique<Botan::DH_PublicKey>(group, safe_get(y));
498 *key = new botan_pubkey_struct(std::move(dh));
499 return BOTAN_FFI_SUCCESS;
500 });
501#else
502 BOTAN_UNUSED(key, p, g, y);
504#endif
505}
506
507/* ECDH + x25519 specific operations */
508
509int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) {
510 if(param_str == nullptr) {
512 }
513
514 const std::string params(param_str);
515
516 if(params == "curve25519") {
517 return botan_privkey_create(key_obj, "Curve25519", "", rng_obj);
518 }
519
520 return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj);
521}
522
524 const botan_mp_t public_x,
525 const botan_mp_t public_y,
526 const char* curve_name) {
527#if defined(BOTAN_HAS_ECDH)
528 return ffi_guard_thunk(__func__, [=]() -> int {
529 std::unique_ptr<Botan::ECDH_PublicKey> p_key;
530 int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name);
531
532 if(rc == BOTAN_FFI_SUCCESS) {
533 *key = new botan_pubkey_struct(std::move(p_key));
534 }
535 return rc;
536 });
537#else
538 BOTAN_UNUSED(key, public_x, public_y, curve_name);
540#endif
541}
542
543int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
544#if defined(BOTAN_HAS_ECDH)
545 return ffi_guard_thunk(__func__, [=]() -> int {
546 std::unique_ptr<Botan::ECDH_PrivateKey> p_key;
547 int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
548 if(rc == BOTAN_FFI_SUCCESS) {
549 *key = new botan_privkey_struct(std::move(p_key));
550 }
551 return rc;
552 });
553#else
554 BOTAN_UNUSED(key, scalar, curve_name);
556#endif
557}
558
559/* SM2 specific operations */
560
562 uint8_t out[], size_t* out_len, const char* ident, const char* hash_algo, const botan_pubkey_t key) {
563 if(out == nullptr || out_len == nullptr) {
565 }
566 if(ident == nullptr || hash_algo == nullptr || key == nullptr) {
568 }
569
570#if defined(BOTAN_HAS_SM2)
571 return ffi_guard_thunk(__func__, [=]() -> int {
572 const Botan::Public_Key& pub_key = safe_get(key);
573 const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key);
574
575 if(ec_key == nullptr) {
577 }
578
579 if(ec_key->algo_name() != "SM2") {
581 }
582
583 const std::string ident_str(ident);
584 std::unique_ptr<Botan::HashFunction> hash = Botan::HashFunction::create_or_throw(hash_algo);
585
586 const std::vector<uint8_t> za = Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), ec_key->public_point());
587
588 return write_vec_output(out, out_len, za);
589 });
590#else
592#endif
593}
594
596 const botan_mp_t public_x,
597 const botan_mp_t public_y,
598 const char* curve_name) {
599#if defined(BOTAN_HAS_SM2)
600 return ffi_guard_thunk(__func__, [=]() -> int {
601 std::unique_ptr<Botan::SM2_PublicKey> p_key;
602 if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) {
603 *key = new botan_pubkey_struct(std::move(p_key));
604 return BOTAN_FFI_SUCCESS;
605 }
607 });
608#else
609 BOTAN_UNUSED(key, public_x, public_y, curve_name);
611#endif
612}
613
614int botan_privkey_load_sm2(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
615#if defined(BOTAN_HAS_SM2)
616 return ffi_guard_thunk(__func__, [=]() -> int {
617 std::unique_ptr<Botan::SM2_PrivateKey> p_key;
618 int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name);
619
620 if(rc == BOTAN_FFI_SUCCESS) {
621 *key = new botan_privkey_struct(std::move(p_key));
622 }
623 return rc;
624 });
625#else
626 BOTAN_UNUSED(key, scalar, curve_name);
628#endif
629}
630
632 const botan_mp_t public_x,
633 const botan_mp_t public_y,
634 const char* curve_name) {
635 return botan_pubkey_load_sm2(key, public_x, public_y, curve_name);
636}
637
638int botan_privkey_load_sm2_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) {
639 return botan_privkey_load_sm2(key, scalar, curve_name);
640}
641
642/* Ed25519 specific operations */
643
644int botan_privkey_load_ed25519(botan_privkey_t* key, const uint8_t privkey[32]) {
645#if defined(BOTAN_HAS_ED25519)
646 *key = nullptr;
647 return ffi_guard_thunk(__func__, [=]() -> int {
648 const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
649 auto ed25519 = std::make_unique<Botan::Ed25519_PrivateKey>(privkey_vec);
650 *key = new botan_privkey_struct(std::move(ed25519));
651 return BOTAN_FFI_SUCCESS;
652 });
653#else
654 BOTAN_UNUSED(key, privkey);
656#endif
657}
658
659int botan_pubkey_load_ed25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
660#if defined(BOTAN_HAS_ED25519)
661 *key = nullptr;
662 return ffi_guard_thunk(__func__, [=]() -> int {
663 const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
664 auto ed25519 = std::make_unique<Botan::Ed25519_PublicKey>(pubkey_vec);
665 *key = new botan_pubkey_struct(std::move(ed25519));
666 return BOTAN_FFI_SUCCESS;
667 });
668#else
669 BOTAN_UNUSED(key, pubkey);
671#endif
672}
673
675#if defined(BOTAN_HAS_ED25519)
676 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
677 if(auto ed = dynamic_cast<const Botan::Ed25519_PrivateKey*>(&k)) {
678 const auto ed_key = ed->raw_private_key_bits();
679 if(ed_key.size() != 64)
681 Botan::copy_mem(output, ed_key.data(), ed_key.size());
682 return BOTAN_FFI_SUCCESS;
683 } else {
685 }
686 });
687#else
688 BOTAN_UNUSED(key, output);
690#endif
691}
692
694#if defined(BOTAN_HAS_ED25519)
695 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
696 if(auto ed = dynamic_cast<const Botan::Ed25519_PublicKey*>(&k)) {
697 const std::vector<uint8_t>& ed_key = ed->get_public_key();
698 if(ed_key.size() != 32)
700 Botan::copy_mem(output, ed_key.data(), ed_key.size());
701 return BOTAN_FFI_SUCCESS;
702 } else {
704 }
705 });
706#else
707 BOTAN_UNUSED(key, output);
709#endif
710}
711
712/* X25519 specific operations */
713
714int botan_privkey_load_x25519(botan_privkey_t* key, const uint8_t privkey[32]) {
715#if defined(BOTAN_HAS_X25519)
716 *key = nullptr;
717 return ffi_guard_thunk(__func__, [=]() -> int {
718 const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32);
719 auto x25519 = std::make_unique<Botan::X25519_PrivateKey>(privkey_vec);
720 *key = new botan_privkey_struct(std::move(x25519));
721 return BOTAN_FFI_SUCCESS;
722 });
723#else
724 BOTAN_UNUSED(key, privkey);
726#endif
727}
728
729int botan_pubkey_load_x25519(botan_pubkey_t* key, const uint8_t pubkey[32]) {
730#if defined(BOTAN_HAS_X25519)
731 *key = nullptr;
732 return ffi_guard_thunk(__func__, [=]() -> int {
733 const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32);
734 auto x25519 = std::make_unique<Botan::X25519_PublicKey>(pubkey_vec);
735 *key = new botan_pubkey_struct(std::move(x25519));
736 return BOTAN_FFI_SUCCESS;
737 });
738#else
739 BOTAN_UNUSED(key, pubkey);
741#endif
742}
743
745#if defined(BOTAN_HAS_X25519)
746 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
747 if(auto x25519 = dynamic_cast<const Botan::X25519_PrivateKey*>(&k)) {
748 const auto x25519_key = x25519->raw_private_key_bits();
749 if(x25519_key.size() != 32)
751 Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
752 return BOTAN_FFI_SUCCESS;
753 } else {
755 }
756 });
757#else
758 BOTAN_UNUSED(key, output);
760#endif
761}
762
763int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, uint8_t output[32]) {
764#if defined(BOTAN_HAS_X25519)
765 return BOTAN_FFI_VISIT(key, [=](const auto& k) {
766 if(auto x25519 = dynamic_cast<const Botan::X25519_PublicKey*>(&k)) {
767 const std::vector<uint8_t>& x25519_key = x25519->public_value();
768 if(x25519_key.size() != 32)
770 Botan::copy_mem(output, x25519_key.data(), x25519_key.size());
771 return BOTAN_FFI_SUCCESS;
772 } else {
774 }
775 });
776#else
777 BOTAN_UNUSED(key, output);
779#endif
780}
781
782/*
783* Algorithm specific key operations: Kyber
784*/
785
786int botan_privkey_load_kyber(botan_privkey_t* key, const uint8_t privkey[], size_t key_len) {
787#if defined(BOTAN_HAS_KYBER)
788 *key = nullptr;
789 switch(key_len) {
790 case 1632:
791 return ffi_guard_thunk(__func__, [=]() -> int {
792 const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 1632);
793 auto kyber512 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber512_R3);
794 *key = new botan_privkey_struct(std::move(kyber512));
795 return BOTAN_FFI_SUCCESS;
796 });
797 case 2400:
798 return ffi_guard_thunk(__func__, [=]() -> int {
799 const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
800 auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768_R3);
801 *key = new botan_privkey_struct(std::move(kyber768));
802 return BOTAN_FFI_SUCCESS;
803 });
804 case 3168:
805 return ffi_guard_thunk(__func__, [=]() -> int {
806 const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 3168);
807 auto kyber1024 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber1024_R3);
808 *key = new botan_privkey_struct(std::move(kyber1024));
809 return BOTAN_FFI_SUCCESS;
810 });
811 default:
812 BOTAN_UNUSED(key, privkey, key_len);
814 }
815#else
816 BOTAN_UNUSED(key, privkey);
818#endif
819}
820
821int botan_pubkey_load_kyber(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len) {
822#if defined(BOTAN_HAS_KYBER)
823 *key = nullptr;
824 switch(key_len) {
825 case 800:
826 return ffi_guard_thunk(__func__, [=]() -> int {
827 const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 800);
828 auto kyber512 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber512_R3);
829 *key = new botan_pubkey_struct(std::move(kyber512));
830 return BOTAN_FFI_SUCCESS;
831 });
832 case 1184:
833 return ffi_guard_thunk(__func__, [=]() -> int {
834 const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
835 auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768_R3);
836 *key = new botan_pubkey_struct(std::move(kyber768));
837 return BOTAN_FFI_SUCCESS;
838 });
839 case 1568:
840 return ffi_guard_thunk(__func__, [=]() -> int {
841 const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1568);
842 auto kyber1024 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber1024_R3);
843 *key = new botan_pubkey_struct(std::move(kyber1024));
844 return BOTAN_FFI_SUCCESS;
845 });
846 default:
847 BOTAN_UNUSED(key, pubkey, key_len);
849 }
850#else
851 BOTAN_UNUSED(key, pubkey, key_len);
853#endif
854}
855
857#if defined(BOTAN_HAS_KYBER)
858 return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
859 if(auto kyber = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k)) {
860 return invoke_view_callback(view, ctx, kyber->raw_private_key_bits());
861 } else {
863 }
864 });
865#else
866 BOTAN_UNUSED(key, ctx, view);
868#endif
869}
870
872#if defined(BOTAN_HAS_KYBER)
873 return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
874 if(auto kyber = dynamic_cast<const Botan::Kyber_PublicKey*>(&k)) {
875 return invoke_view_callback(view, ctx, kyber->public_key_bits());
876 } else {
878 }
879 });
880#else
881 BOTAN_UNUSED(key, ctx, view);
883#endif
884}
885
887#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
888 return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
889 if(auto ecc = dynamic_cast<const Botan::EC_PublicKey*>(&k)) {
890 auto pt = ecc->public_point().encode(Botan::EC_Point_Format::Uncompressed);
891 return invoke_view_callback(view, ctx, pt);
892 } else {
894 }
895 });
896#else
897 BOTAN_UNUSED(key, view, ctx);
899#endif
900}
901
902int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) {
903 const std::string mce_params = std::to_string(n) + "," + std::to_string(t);
904 return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj);
905}
906
908 const char* aead,
909 const uint8_t ct[],
910 size_t ct_len,
911 const uint8_t ad[],
912 size_t ad_len,
913 uint8_t out[],
914 size_t* out_len) {
915 BOTAN_UNUSED(mce_key_obj, aead, ct, ct_len, ad, ad_len, out, out_len);
917}
918
920 botan_rng_t rng_obj,
921 const char* aead,
922 const uint8_t pt[],
923 size_t pt_len,
924 const uint8_t ad[],
925 size_t ad_len,
926 uint8_t out[],
927 size_t* out_len) {
928 BOTAN_UNUSED(mce_key_obj, rng_obj, aead, pt, pt_len, ad, ad_len, out, out_len);
930}
931}
#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
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:298
struct botan_pubkey_struct * botan_pubkey_t
Definition ffi.h:1259
struct botan_privkey_struct * botan_privkey_t
Definition ffi.h:1045
int(* botan_view_bin_fn)(botan_view_ctx view_ctx, const uint8_t *data, size_t len)
Definition ffi.h:129
#define BOTAN_PRIVKEY_EXPORT_FLAG_PEM
Definition ffi.h:1129
struct botan_mp_struct * botan_mp_t
Definition ffi.h:848
void * botan_view_ctx
Definition ffi.h:120
struct botan_rng_struct * botan_rng_t
Definition ffi.h:246
#define BOTAN_PRIVKEY_EXPORT_FLAG_DER
Definition ffi.h:1128
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:110
@ BOTAN_FFI_ERROR_UNKNOWN_ERROR
Definition ffi.h:117
@ BOTAN_FFI_ERROR_BAD_FLAG
Definition ffi.h:103
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:104
@ BOTAN_FFI_SUCCESS
Definition ffi.h:89
@ BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE
Definition ffi.h:95
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition ffi.h:105
BOTAN_DLL 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
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_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_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_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_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_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_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_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)
#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