/* * (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 #include #include #include #include #include #include #if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) #include #endif #if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY) #include #endif #if defined(BOTAN_HAS_RSA) #include #endif #if defined(BOTAN_HAS_ELGAMAL) #include #endif #if defined(BOTAN_HAS_DSA) #include #endif #if defined(BOTAN_HAS_ECDSA) #include #endif #if defined(BOTAN_HAS_SM2) #include #include #endif #if defined(BOTAN_HAS_ECDH) #include #endif #if defined(BOTAN_HAS_CURVE_25519) #include #endif #if defined(BOTAN_HAS_ED25519) #include #endif #if defined(BOTAN_HAS_MCELIECE) #include #endif #if defined(BOTAN_HAS_MCEIES) #include #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) #include #endif namespace { #if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) // These are always called within an existing try/catch block template int privkey_load_ec(std::unique_ptr& 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 int pubkey_load_ec(std::unique_ptr& 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(&key)) { if(field == "n") return rsa->get_n(); else if(field == "e") return rsa->get_e(); else throw Botan::Exception("Field not supported"); } #endif #if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY) // Handles DSA, ElGamal, etc if(const Botan::DL_Scheme_PublicKey* dl = dynamic_cast(&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::Exception("Field not supported"); } #endif #if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) if(const Botan::EC_PublicKey* ecc = dynamic_cast(&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::Exception("Field not supported"); } #endif // Some other algorithm type not supported by this function throw Botan::Exception("Unsupported algorithm type for botan_pubkey_get_field"); } 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(&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(&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(&key)) { if(field == "x") return ecc->private_value(); else return pubkey_get_field(key, field); } #endif // Some other algorithm type not supported by this function throw Botan::Exception("Unsupported algorithm type for botan_privkey_get_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(BOTAN_CURRENT_FUNCTION, [=]() -> 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 src(bits, bits + len); return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> 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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(&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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(BOTAN_CURRENT_FUNCTION, [=]() -> int { std::unique_ptr 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(BOTAN_CURRENT_FUNCTION, [=]() -> int { std::unique_ptr 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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(BOTAN_CURRENT_FUNCTION, [=]() -> int { std::unique_ptr 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(BOTAN_CURRENT_FUNCTION, [=]() -> int { std::unique_ptr 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(BOTAN_CURRENT_FUNCTION, [=]() -> int { const Botan::Public_Key& pub_key = safe_get(key); const Botan::EC_PublicKey* ec_key = dynamic_cast(&pub_key); if(ec_key == nullptr) return BOTAN_FFI_ERROR_BAD_PARAMETER; if(ec_key->algo_name() != "SM2_Sig" && ec_key->algo_name() != "SM2_Enc") return BOTAN_FFI_ERROR_BAD_PARAMETER; const std::string ident_str(ident); std::unique_ptr hash = Botan::HashFunction::create_or_throw(hash_algo); const std::vector 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(BOTAN_CURRENT_FUNCTION, [=]() -> int { std::unique_ptr 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(BOTAN_CURRENT_FUNCTION, [=]() -> int { std::unique_ptr 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) { #if defined(BOTAN_HAS_SM2) return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int { std::unique_ptr 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_enc(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) { #if defined(BOTAN_HAS_SM2) return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int { std::unique_ptr 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 } /* 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(BOTAN_CURRENT_FUNCTION, [=]() -> int { const Botan::secure_vector 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(BOTAN_CURRENT_FUNCTION, [=]() -> int { const std::vector 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(&k)) { const Botan::secure_vector& 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(&k)) { const std::vector& 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 } 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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(&key); if(!mce) return BOTAN_FFI_ERROR_BAD_PARAMETER; const Botan::secure_vector 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(BOTAN_CURRENT_FUNCTION, [=]() -> 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(&key); if(!mce) return BOTAN_FFI_ERROR_BAD_PARAMETER; Botan::secure_vector 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 }); } }