diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/botan/src/lib/ffi/ffi_pkey_algs.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/botan/src/lib/ffi/ffi_pkey_algs.cpp')
-rw-r--r-- | comm/third_party/botan/src/lib/ffi/ffi_pkey_algs.cpp | 980 |
1 files changed, 980 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/ffi/ffi_pkey_algs.cpp b/comm/third_party/botan/src/lib/ffi/ffi_pkey_algs.cpp new file mode 100644 index 0000000000..9f5d543100 --- /dev/null +++ b/comm/third_party/botan/src/lib/ffi/ffi_pkey_algs.cpp @@ -0,0 +1,980 @@ +/* +* (C) 2015,2017 Jack Lloyd +* (C) 2017 Ribose Inc +* (C) 2018 René Korthaus, Rohde & Schwarz Cybersecurity +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/ffi.h> +#include <botan/hash.h> +#include <botan/pem.h> +#include <botan/internal/ffi_util.h> +#include <botan/internal/ffi_pkey.h> +#include <botan/internal/ffi_rng.h> +#include <botan/internal/ffi_mp.h> + +#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) + #include <botan/ecc_key.h> +#endif + +#if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY) + #include <botan/dl_algo.h> +#endif + +#if defined(BOTAN_HAS_RSA) + #include <botan/rsa.h> +#endif + +#if defined(BOTAN_HAS_ELGAMAL) + #include <botan/elgamal.h> +#endif + +#if defined(BOTAN_HAS_DSA) + #include <botan/dsa.h> +#endif + +#if defined(BOTAN_HAS_ECDSA) + #include <botan/ecdsa.h> +#endif + +#if defined(BOTAN_HAS_SM2) + #include <botan/sm2.h> +#endif + +#if defined(BOTAN_HAS_ECDH) + #include <botan/ecdh.h> +#endif + +#if defined(BOTAN_HAS_CURVE_25519) + #include <botan/curve25519.h> +#endif + +#if defined(BOTAN_HAS_ED25519) + #include <botan/ed25519.h> +#endif + +#if defined(BOTAN_HAS_MCELIECE) + #include <botan/mceliece.h> +#endif + +#if defined(BOTAN_HAS_MCEIES) + #include <botan/mceies.h> +#endif + +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + #include <botan/dh.h> +#endif + + +namespace { + +#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) + +// These are always called within an existing try/catch block + +template<class ECPrivateKey_t> +int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, + const Botan::BigInt& scalar, + const char* curve_name) + { + if(curve_name == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + + Botan::Null_RNG null_rng; + Botan::EC_Group grp(curve_name); + key.reset(new ECPrivateKey_t(null_rng, grp, scalar)); + return BOTAN_FFI_SUCCESS; + } + +template<class ECPublicKey_t> +int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key, + const Botan::BigInt& public_x, + const Botan::BigInt& public_y, + const char* curve_name) + { + if(curve_name == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + + Botan::EC_Group grp(curve_name); + Botan::PointGFp uncompressed_point = grp.point(public_x, public_y); + key.reset(new ECPublicKey_t(grp, uncompressed_point)); + return BOTAN_FFI_SUCCESS; + } + +#endif + +Botan::BigInt pubkey_get_field(const Botan::Public_Key& key, + const std::string& field) + { + // Maybe this should be `return key.get_integer_field(field_name)`? + +#if defined(BOTAN_HAS_RSA) + if(const Botan::RSA_PublicKey* rsa = dynamic_cast<const Botan::RSA_PublicKey*>(&key)) + { + if(field == "n") + return rsa->get_n(); + else if(field == "e") + return rsa->get_e(); + else + throw Botan_FFI::FFI_Error("Bad field", BOTAN_FFI_ERROR_BAD_PARAMETER); + } +#endif + +#if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY) + // Handles DSA, ElGamal, etc + if(const Botan::DL_Scheme_PublicKey* dl = dynamic_cast<const Botan::DL_Scheme_PublicKey*>(&key)) + { + if(field == "p") + return dl->group_p(); + else if(field == "q") + return dl->group_q(); + else if(field == "g") + return dl->group_g(); + else if(field == "y") + return dl->get_y(); + else + throw Botan_FFI::FFI_Error("Bad field", BOTAN_FFI_ERROR_BAD_PARAMETER); + } +#endif + +#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) + if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key)) + { + if(field == "public_x") + return ecc->public_point().get_affine_x(); + else if(field == "public_y") + return ecc->public_point().get_affine_y(); + else if(field == "base_x") + return ecc->domain().get_g_x(); + else if(field == "base_y") + return ecc->domain().get_g_y(); + else if(field == "p") + return ecc->domain().get_p(); + else if(field == "a") + return ecc->domain().get_a(); + else if(field == "b") + return ecc->domain().get_b(); + else if(field == "cofactor") + return ecc->domain().get_cofactor(); + else if(field == "order") + return ecc->domain().get_order(); + else + throw Botan_FFI::FFI_Error("Bad field", BOTAN_FFI_ERROR_BAD_PARAMETER); + } +#endif + + // Some other algorithm type not supported by this function + throw Botan_FFI::FFI_Error("Field getter not implemented for this algorithm type", + BOTAN_FFI_ERROR_NOT_IMPLEMENTED); + } + +Botan::BigInt privkey_get_field(const Botan::Private_Key& key, + const std::string& field) + { + //return key.get_integer_field(field); + +#if defined(BOTAN_HAS_RSA) + + if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&key)) + { + if(field == "p") + return rsa->get_p(); + else if(field == "q") + return rsa->get_q(); + else if(field == "d") + return rsa->get_d(); + else if(field == "c") + return rsa->get_c(); + else if(field == "d1") + return rsa->get_d1(); + else if(field == "d2") + return rsa->get_d2(); + else + return pubkey_get_field(key, field); + } +#endif + +#if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY) + // Handles DSA, ElGamal, etc + if(const Botan::DL_Scheme_PrivateKey* dl = dynamic_cast<const Botan::DL_Scheme_PrivateKey*>(&key)) + { + if(field == "x") + return dl->get_x(); + else + return pubkey_get_field(key, field); + } +#endif + +#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) + if(const Botan::EC_PrivateKey* ecc = dynamic_cast<const Botan::EC_PrivateKey*>(&key)) + { + if(field == "x") + return ecc->private_value(); + else + return pubkey_get_field(key, field); + } +#endif + + return pubkey_get_field(key, field); + } + +} + +extern "C" { + +using namespace Botan_FFI; + +int botan_pubkey_get_field(botan_mp_t output, + botan_pubkey_t key, + const char* field_name_cstr) + { + if(field_name_cstr == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + + const std::string field_name(field_name_cstr); + + return BOTAN_FFI_DO(Botan::Public_Key, key, k, { + safe_get(output) = pubkey_get_field(k, field_name); + }); + } + +int botan_privkey_get_field(botan_mp_t output, + botan_privkey_t key, + const char* field_name_cstr) + { + if(field_name_cstr == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + + const std::string field_name(field_name_cstr); + + return BOTAN_FFI_DO(Botan::Private_Key, key, k, { + safe_get(output) = privkey_get_field(k, field_name); + }); + } + +/* RSA specific operations */ + +int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) + { + if(n_bits < 1024 || n_bits > 16*1024) + return BOTAN_FFI_ERROR_BAD_PARAMETER; + + std::string n_str = std::to_string(n_bits); + + return botan_privkey_create(key_obj, "RSA", n_str.c_str(), rng_obj); + } + +int botan_privkey_load_rsa(botan_privkey_t* key, + botan_mp_t rsa_p, botan_mp_t rsa_q, botan_mp_t rsa_e) + { +#if defined(BOTAN_HAS_RSA) + *key = nullptr; + + return ffi_guard_thunk(__func__, [=]() -> int { + *key = new botan_privkey_struct(new Botan::RSA_PrivateKey(safe_get(rsa_p), + safe_get(rsa_q), + safe_get(rsa_e))); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, rsa_p, rsa_q, rsa_e); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, + const uint8_t bits[], + size_t len) + { +#if defined(BOTAN_HAS_RSA) + *key = nullptr; + + Botan::secure_vector<uint8_t> src(bits, bits + len); + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::AlgorithmIdentifier alg_id("RSA", Botan::AlgorithmIdentifier::USE_NULL_PARAM); + *key = new botan_privkey_struct(new Botan::RSA_PrivateKey(alg_id, src)); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, bits, len); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_pubkey_load_rsa(botan_pubkey_t* key, + botan_mp_t n, botan_mp_t e) + { +#if defined(BOTAN_HAS_RSA) + *key = nullptr; + return ffi_guard_thunk(__func__, [=]() -> int { + *key = new botan_pubkey_struct(new Botan::RSA_PublicKey(safe_get(n), safe_get(e))); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, n, e); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key) + { + return botan_privkey_get_field(p, key, "p"); + } + +int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key) + { + return botan_privkey_get_field(q, key, "q"); + } + +int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key) + { + return botan_privkey_get_field(n, key, "n"); + } + +int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key) + { + return botan_privkey_get_field(e, key, "e"); + } + +int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key) + { + return botan_privkey_get_field(d, key, "d"); + } + +int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key) + { + return botan_pubkey_get_field(e, key, "e"); + } + +int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) + { + return botan_pubkey_get_field(n, key, "n"); + } + +int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, + uint8_t out[], size_t* out_len, + uint32_t flags) + { +#if defined(BOTAN_HAS_RSA) + return BOTAN_FFI_DO(Botan::Private_Key, rsa_key, k, { + if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) + { + if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) + return write_vec_output(out, out_len, rsa->private_key_bits()); + else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) + return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), + "RSA PRIVATE KEY")); + else + return BOTAN_FFI_ERROR_BAD_FLAG; + } + else + { + return BOTAN_FFI_ERROR_BAD_PARAMETER; + } + }); +#else + BOTAN_UNUSED(rsa_key, out, out_len); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +/* DSA specific operations */ +int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) + { +#if defined(BOTAN_HAS_DSA) + + if ((rng_obj == nullptr) || (key == nullptr)) + return BOTAN_FFI_ERROR_NULL_POINTER; + + if ((pbits % 64) || (qbits % 8) || + (pbits < 1024) || (pbits > 3072) || + (qbits < 160) || (qbits > 256)) { + return BOTAN_FFI_ERROR_BAD_PARAMETER; + } + + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::RandomNumberGenerator& rng = safe_get(rng_obj); + Botan::DL_Group group(rng, Botan::DL_Group::Prime_Subgroup, pbits, qbits); + *key = new botan_privkey_struct(new Botan::DSA_PrivateKey(rng, group)); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, rng_obj, pbits, qbits); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +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) + { +#if defined(BOTAN_HAS_DSA) + *key = nullptr; + + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::Null_RNG null_rng; + Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g)); + *key = new botan_privkey_struct(new Botan::DSA_PrivateKey(null_rng, group, safe_get(x))); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, p, q, g, x); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +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) + { +#if defined(BOTAN_HAS_DSA) + *key = nullptr; + + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g)); + *key = new botan_pubkey_struct(new Botan::DSA_PublicKey(group, safe_get(y))); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, p, q, g, y); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key) + { + return botan_privkey_get_field(x, key, "x"); + } + +int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key) + { + return botan_pubkey_get_field(p, key, "p"); + } + +int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key) + { + return botan_pubkey_get_field(q, key, "q"); + } + +int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key) + { + return botan_pubkey_get_field(g, key, "g"); + } + +int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key) + { + return botan_pubkey_get_field(y, key, "y"); + } + +int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) + { + return botan_privkey_create(key_obj, "ECDSA", param_str, rng_obj); + } + +/* ECDSA specific operations */ + +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) + { +#if defined(BOTAN_HAS_ECDSA) + return ffi_guard_thunk(__func__, [=]() -> int { + std::unique_ptr<Botan::ECDSA_PublicKey> p_key; + + int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name); + if(rc == BOTAN_FFI_SUCCESS) + *key = new botan_pubkey_struct(p_key.release()); + + return rc; + }); +#else + BOTAN_UNUSED(key, public_x, public_y, curve_name); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_privkey_load_ecdsa(botan_privkey_t* key, + const botan_mp_t scalar, + const char* curve_name) + { +#if defined(BOTAN_HAS_ECDSA) + return ffi_guard_thunk(__func__, [=]() -> int { + std::unique_ptr<Botan::ECDSA_PrivateKey> p_key; + int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name); + if(rc == BOTAN_FFI_SUCCESS) + *key = new botan_privkey_struct(p_key.release()); + return rc; + }); +#else + BOTAN_UNUSED(key, scalar, curve_name); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +/* ElGamal specific operations */ +int botan_privkey_create_elgamal(botan_privkey_t* key, + botan_rng_t rng_obj, + size_t pbits, + size_t qbits) + { +#if defined(BOTAN_HAS_ELGAMAL) + + if ((rng_obj == nullptr) || (key == nullptr)) + return BOTAN_FFI_ERROR_NULL_POINTER; + + if ((pbits < 1024) || (qbits<160)) { + return BOTAN_FFI_ERROR_BAD_PARAMETER; + } + + Botan::DL_Group::PrimeType prime_type = ((pbits-1) == qbits) + ? Botan::DL_Group::Strong + : Botan::DL_Group::Prime_Subgroup; + + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::RandomNumberGenerator& rng = safe_get(rng_obj); + Botan::DL_Group group(rng, prime_type, pbits, qbits); + *key = new botan_privkey_struct(new Botan::ElGamal_PrivateKey(rng, group)); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, rng_obj, pbits); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_pubkey_load_elgamal(botan_pubkey_t* key, + botan_mp_t p, botan_mp_t g, botan_mp_t y) + { +#if defined(BOTAN_HAS_ELGAMAL) + *key = nullptr; + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::DL_Group group(safe_get(p), safe_get(g)); + *key = new botan_pubkey_struct(new Botan::ElGamal_PublicKey(group, safe_get(y))); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, p, g, y); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_privkey_load_elgamal(botan_privkey_t* key, + botan_mp_t p, botan_mp_t g, botan_mp_t x) + { +#if defined(BOTAN_HAS_ELGAMAL) + *key = nullptr; + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::Null_RNG null_rng; + Botan::DL_Group group(safe_get(p), safe_get(g)); + *key = new botan_privkey_struct(new Botan::ElGamal_PrivateKey(null_rng, group, safe_get(x))); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, p, g, x); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +/* Diffie Hellman specific operations */ + +int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) + { + return botan_privkey_create(key_obj, "DH", param_str, rng_obj); + } + +int botan_privkey_load_dh(botan_privkey_t* key, + botan_mp_t p, botan_mp_t g, botan_mp_t x) + { +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + *key = nullptr; + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::Null_RNG null_rng; + Botan::DL_Group group(safe_get(p), safe_get(g)); + *key = new botan_privkey_struct(new Botan::DH_PrivateKey(null_rng, group, safe_get(x))); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, p, g, x); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_pubkey_load_dh(botan_pubkey_t* key, + botan_mp_t p, botan_mp_t g, botan_mp_t y) + { +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + *key = nullptr; + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::DL_Group group(safe_get(p), safe_get(g)); + *key = new botan_pubkey_struct(new Botan::DH_PublicKey(group, safe_get(y))); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, p, g, y); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +/* ECDH + x25519 specific operations */ + +int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str) + { + if(param_str == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + + const std::string params(param_str); + + if(params == "curve25519") + return botan_privkey_create(key_obj, "Curve25519", "", rng_obj); + + return botan_privkey_create(key_obj, "ECDH", param_str, rng_obj); + } + +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) + { +#if defined(BOTAN_HAS_ECDH) + return ffi_guard_thunk(__func__, [=]() -> int { + std::unique_ptr<Botan::ECDH_PublicKey> p_key; + int rc = pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name); + + if(rc == BOTAN_FFI_SUCCESS) + *key = new botan_pubkey_struct(p_key.release()); + return rc; + }); +#else + BOTAN_UNUSED(key, public_x, public_y, curve_name); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_privkey_load_ecdh(botan_privkey_t* key, + const botan_mp_t scalar, + const char* curve_name) + { +#if defined(BOTAN_HAS_ECDH) + return ffi_guard_thunk(__func__, [=]() -> int { + std::unique_ptr<Botan::ECDH_PrivateKey> p_key; + int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name); + if(rc == BOTAN_FFI_SUCCESS) + *key = new botan_privkey_struct(p_key.release()); + return rc; + }); +#else + BOTAN_UNUSED(key, scalar, curve_name); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +/* SM2 specific operations */ + +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) + { + if(out == nullptr || out_len == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + if(ident == nullptr || hash_algo == nullptr || key == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + +#if defined(BOTAN_HAS_SM2) + return ffi_guard_thunk(__func__, [=]() -> int { + const Botan::Public_Key& pub_key = safe_get(key); + const Botan::EC_PublicKey* ec_key = dynamic_cast<const Botan::EC_PublicKey*>(&pub_key); + + if(ec_key == nullptr) + return BOTAN_FFI_ERROR_BAD_PARAMETER; + + if(ec_key->algo_name() != "SM2") + return BOTAN_FFI_ERROR_BAD_PARAMETER; + + const std::string ident_str(ident); + std::unique_ptr<Botan::HashFunction> hash = + Botan::HashFunction::create_or_throw(hash_algo); + + const std::vector<uint8_t> za = + Botan::sm2_compute_za(*hash, ident_str, ec_key->domain(), ec_key->public_point()); + + return write_vec_output(out, out_len, za); + }); +#else + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +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) + { +#if defined(BOTAN_HAS_SM2) + return ffi_guard_thunk(__func__, [=]() -> int { + std::unique_ptr<Botan::SM2_PublicKey> p_key; + if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) + { + *key = new botan_pubkey_struct(p_key.release()); + return BOTAN_FFI_SUCCESS; + } + return BOTAN_FFI_ERROR_UNKNOWN_ERROR; + }); +#else + BOTAN_UNUSED(key, public_x, public_y, curve_name); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_privkey_load_sm2(botan_privkey_t* key, + const botan_mp_t scalar, + const char* curve_name) + { +#if defined(BOTAN_HAS_SM2) + return ffi_guard_thunk(__func__, [=]() -> int { + std::unique_ptr<Botan::SM2_PrivateKey> p_key; + int rc = privkey_load_ec(p_key, safe_get(scalar), curve_name); + + if(rc == BOTAN_FFI_SUCCESS) + *key = new botan_privkey_struct(p_key.release()); + return rc; + }); +#else + BOTAN_UNUSED(key, scalar, curve_name); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +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) + { + return botan_pubkey_load_sm2(key, public_x, public_y, curve_name); + } + +int botan_privkey_load_sm2_enc(botan_privkey_t* key, + const botan_mp_t scalar, + const char* curve_name) + { + return botan_privkey_load_sm2(key, scalar, curve_name); + } + +/* Ed25519 specific operations */ + +int botan_privkey_load_ed25519(botan_privkey_t* key, + const uint8_t privkey[32]) + { +#if defined(BOTAN_HAS_ED25519) + *key = nullptr; + return ffi_guard_thunk(__func__, [=]() -> int { + const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32); + *key = new botan_privkey_struct(new Botan::Ed25519_PrivateKey(privkey_vec)); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, privkey); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_pubkey_load_ed25519(botan_pubkey_t* key, + const uint8_t pubkey[32]) + { +#if defined(BOTAN_HAS_ED25519) + *key = nullptr; + return ffi_guard_thunk(__func__, [=]() -> int { + const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32); + *key = new botan_pubkey_struct(new Botan::Ed25519_PublicKey(pubkey_vec)); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, pubkey); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_privkey_ed25519_get_privkey(botan_privkey_t key, + uint8_t output[64]) + { +#if defined(BOTAN_HAS_ED25519) + return BOTAN_FFI_DO(Botan::Private_Key, key, k, { + if(Botan::Ed25519_PrivateKey* ed = dynamic_cast<Botan::Ed25519_PrivateKey*>(&k)) + { + const Botan::secure_vector<uint8_t>& ed_key = ed->get_private_key(); + if(ed_key.size() != 64) + return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE; + Botan::copy_mem(output, ed_key.data(), ed_key.size()); + return BOTAN_FFI_SUCCESS; + } + else + { + return BOTAN_FFI_ERROR_BAD_PARAMETER; + } + }); +#else + BOTAN_UNUSED(key, output); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, + uint8_t output[32]) + { +#if defined(BOTAN_HAS_ED25519) + return BOTAN_FFI_DO(Botan::Public_Key, key, k, { + if(Botan::Ed25519_PublicKey* ed = dynamic_cast<Botan::Ed25519_PublicKey*>(&k)) + { + const std::vector<uint8_t>& ed_key = ed->get_public_key(); + if(ed_key.size() != 32) + return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE; + Botan::copy_mem(output, ed_key.data(), ed_key.size()); + return BOTAN_FFI_SUCCESS; + } + else + { + return BOTAN_FFI_ERROR_BAD_PARAMETER; + } + }); +#else + BOTAN_UNUSED(key, output); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +/* X25519 specific operations */ + +int botan_privkey_load_x25519(botan_privkey_t* key, + const uint8_t privkey[32]) + { +#if defined(BOTAN_HAS_X25519) + *key = nullptr; + return ffi_guard_thunk(__func__, [=]() -> int { + const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 32); + *key = new botan_privkey_struct(new Botan::X25519_PrivateKey(privkey_vec)); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, privkey); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_pubkey_load_x25519(botan_pubkey_t* key, + const uint8_t pubkey[32]) + { +#if defined(BOTAN_HAS_X25519) + *key = nullptr; + return ffi_guard_thunk(__func__, [=]() -> int { + const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 32); + *key = new botan_pubkey_struct(new Botan::X25519_PublicKey(pubkey_vec)); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, pubkey); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_privkey_x25519_get_privkey(botan_privkey_t key, + uint8_t output[32]) + { +#if defined(BOTAN_HAS_X25519) + return BOTAN_FFI_DO(Botan::Private_Key, key, k, { + if(Botan::X25519_PrivateKey* x25519 = dynamic_cast<Botan::X25519_PrivateKey*>(&k)) + { + const Botan::secure_vector<uint8_t>& x25519_key = x25519->get_x(); + if(x25519_key.size() != 32) + return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE; + Botan::copy_mem(output, x25519_key.data(), x25519_key.size()); + return BOTAN_FFI_SUCCESS; + } + else + { + return BOTAN_FFI_ERROR_BAD_PARAMETER; + } + }); +#else + BOTAN_UNUSED(key, output); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key, + uint8_t output[32]) + { +#if defined(BOTAN_HAS_X25519) + return BOTAN_FFI_DO(Botan::Public_Key, key, k, { + if(Botan::X25519_PublicKey* x25519 = dynamic_cast<Botan::X25519_PublicKey*>(&k)) + { + const std::vector<uint8_t>& x25519_key = x25519->public_value(); + if(x25519_key.size() != 32) + return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE; + Botan::copy_mem(output, x25519_key.data(), x25519_key.size()); + return BOTAN_FFI_SUCCESS; + } + else + { + return BOTAN_FFI_ERROR_BAD_PARAMETER; + } + }); +#else + BOTAN_UNUSED(key, output); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + +int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t) + { + const std::string mce_params = std::to_string(n) + "," + std::to_string(t); + return botan_privkey_create(key_obj, "McEliece", mce_params.c_str(), rng_obj); + } + +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) + { + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::Private_Key& key = safe_get(mce_key_obj); + +#if defined(BOTAN_HAS_MCELIECE) && defined(BOTAN_HAS_MCEIES) + Botan::McEliece_PrivateKey* mce = dynamic_cast<Botan::McEliece_PrivateKey*>(&key); + if(!mce) + return BOTAN_FFI_ERROR_BAD_PARAMETER; + + const Botan::secure_vector<uint8_t> pt = mceies_decrypt(*mce, ct, ct_len, ad, ad_len, aead); + return write_vec_output(out, out_len, pt); +#else + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + }); + } + +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) + { + return ffi_guard_thunk(__func__, [=]() -> int { + Botan::Public_Key& key = safe_get(mce_key_obj); + Botan::RandomNumberGenerator& rng = safe_get(rng_obj); + +#if defined(BOTAN_HAS_MCELIECE) && defined(BOTAN_HAS_MCEIES) + Botan::McEliece_PublicKey* mce = dynamic_cast<Botan::McEliece_PublicKey*>(&key); + if(!mce) + return BOTAN_FFI_ERROR_BAD_PARAMETER; + + Botan::secure_vector<uint8_t> ct = mceies_encrypt(*mce, pt, pt_len, ad, ad_len, rng, aead); + return write_vec_output(out, out_len, ct); +#else + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + }); + } + +} |