diff options
-rw-r--r-- | src/lib/ffi/ffi.cpp | 167 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 32 |
2 files changed, 116 insertions, 83 deletions
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp index 9940c380e..4fcb73f82 100644 --- a/src/lib/ffi/ffi.cpp +++ b/src/lib/ffi/ffi.cpp @@ -330,8 +330,66 @@ Botan::BigInt privkey_get_field(const Botan::Private_Key& key, throw Botan::Exception("Unsupported algorithm type for botan_privkey_get_field"); } +template<class ECPrivateKey_t> +int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, + const Botan::BigInt& scalar, + const char* curve_name) + { +#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) + + if(curve_name == nullptr) + return -1; + + try + { + Botan::Null_RNG null_rng; + Botan::EC_Group grp(curve_name); + key.reset(new ECPrivateKey_t(null_rng, grp, scalar)); + return 0; + } + catch(std::exception& e) + { + log_exception(BOTAN_CURRENT_FUNCTION, e.what()); + } + return -1; +#else + BOTAN_UNUSED(key, scalar, scalar_len, curve_name); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } } +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 defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) + + if(curve_name == nullptr) + return -1; + + try + { + Botan::Null_RNG null_rng; + Botan::EC_Group grp(curve_name); + Botan::PointGFp uncompressed_point(grp.get_curve(), public_x, public_y); + key.reset(new ECPublicKey_t(grp, uncompressed_point)); + return 0; + } + catch(std::exception& e) + { + log_exception(BOTAN_CURRENT_FUNCTION, e.what()); + } + return -1; +#else + BOTAN_UNUSED(key, public_x, public_y, curve_name); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + + extern "C" { #define BOTAN_FFI_DECLARE_STRUCT(NAME, TYPE, MAGIC) \ @@ -1699,85 +1757,20 @@ int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key, #endif } -namespace { -/* Those functions can't be defined in namespace {} that's located higher in this file - * as they use botan_privkey_struct/botan_pubkey_struct structs. - */ -int privkey_load_ec(botan_privkey_t* key, - const botan_mp_t scalar, - const char* curve_name, - const std::string& algo_name) +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_ECC_PUBLIC_KEY_CRYPTO) - *key = nullptr; - try - { - Botan::Null_RNG null_rng; - Botan::EC_Group grp(curve_name); - if (algo_name.compare("ECDSA") == 0) { - *key = new botan_privkey_struct(new Botan::ECDSA_PrivateKey(null_rng, grp, safe_get(scalar))); - } else if (algo_name.compare("ECDH") == 0) { - *key = new botan_privkey_struct(new Botan::ECDH_PrivateKey(null_rng, grp, safe_get(scalar))); - } else { - return -1; - } - - return 0; - } - catch(std::exception& e) - { - log_exception(BOTAN_CURRENT_FUNCTION, e.what()); - } - return -1; -#else - BOTAN_UNUSED(key, scalar, scalar_len, curve_name); - return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; -#endif - } -int pubkey_load_ec(botan_pubkey_t* key, - const botan_mp_t public_x, - const botan_mp_t public_y, - const char* curve_name, - const std::string& algo_name) - { -#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) - if(key == nullptr || curve_name == nullptr) - return -1; - *key = nullptr; - try + std::unique_ptr<Botan::ECDSA_PublicKey> p_key; + if(!pubkey_load_ec(p_key, safe_get(public_x), safe_get(public_y), curve_name)) { - Botan::Null_RNG null_rng; - Botan::EC_Group grp(curve_name); - Botan::PointGFp uncompressed_point(grp.get_curve(), safe_get(public_x), safe_get(public_y)); - if (algo_name.compare("ECDSA") == 0) { - *key = new botan_pubkey_struct(new Botan::ECDSA_PublicKey(grp, uncompressed_point)); - } else if (algo_name.compare("ECDH") == 0) { - *key = new botan_pubkey_struct(new Botan::ECDH_PublicKey(grp, uncompressed_point)); - } else { - return -1; - } - + *key = new botan_pubkey_struct(p_key.release()); return 0; } - catch(std::exception& e) - { - log_exception(BOTAN_CURRENT_FUNCTION, e.what()); - } - return -1; -#else - BOTAN_UNUSED(key, public_x, public_y, curve_name); - return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; -#endif - } -} // namespace {} -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) - { - return pubkey_load_ec(key, public_x, public_y, curve_name, "ECDSA"); + return -1; } int botan_pubkey_load_ecdh(botan_pubkey_t* key, @@ -1785,21 +1778,41 @@ int botan_pubkey_load_ecdh(botan_pubkey_t* key, const botan_mp_t public_y, const char* curve_name) { - return pubkey_load_ec(key, public_x, public_y, curve_name, "ECDH"); + std::unique_ptr<Botan::ECDH_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 0; + } + + return -1; } int botan_privkey_load_ecdsa(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) { - return privkey_load_ec(key, scalar, curve_name, "ECDSA"); - } + std::unique_ptr<Botan::ECDSA_PrivateKey> p_key; + if(!privkey_load_ec(p_key, safe_get(scalar), curve_name)) + { + *key = new botan_privkey_struct(p_key.release()); + return 0; + } + return -1; + } int botan_privkey_load_ecdh(botan_privkey_t* key, const botan_mp_t scalar, const char* curve_name) { - return privkey_load_ec(key, scalar, curve_name, "ECDH"); + std::unique_ptr<Botan::ECDH_PrivateKey> p_key; + if(!privkey_load_ec(p_key, safe_get(scalar), curve_name)) + { + *key = new botan_privkey_struct(p_key.release()); + return 0; + } + + return -1; } int botan_pubkey_get_field(botan_mp_t output, diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp index dc6b25a48..e9d9b6e20 100644 --- a/src/tests/test_ffi.cpp +++ b/src/tests/test_ffi.cpp @@ -1269,9 +1269,9 @@ class FFI_Unit_Tests : public Test TEST_FFI_OK(botan_pk_op_verify_destroy, (verifier)); } - botan_mp_destroy(private_scalar); - botan_mp_destroy(public_x); - botan_mp_destroy(public_y); + TEST_FFI_OK(botan_mp_destroy, (private_scalar)); + TEST_FFI_OK(botan_mp_destroy, (public_x)); + TEST_FFI_OK(botan_mp_destroy, (public_y)); TEST_FFI_OK(botan_pubkey_destroy, (pub)); TEST_FFI_OK(botan_privkey_destroy, (priv)); TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey)); @@ -1284,6 +1284,13 @@ class FFI_Unit_Tests : public Test { Test::Result result("FFI ECDH"); + botan_mp_t private_scalar, public_x, public_y; + botan_privkey_t loaded_privkey1; + botan_pubkey_t loaded_pubkey1; + botan_mp_init(&private_scalar); + botan_mp_init(&public_x); + botan_mp_init(&public_y); + botan_privkey_t priv1; REQUIRE_FFI_OK(botan_privkey_create_ecdh, (&priv1, rng, "secp256r1")); @@ -1296,11 +1303,20 @@ class FFI_Unit_Tests : public Test botan_pubkey_t pub2; REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub2, priv2)); - ffi_test_pubkey_export(result, pub1, priv1, rng); + /* Reload key-pair1 in order to test functions for key loading */ + TEST_FFI_OK(botan_privkey_get_field, (private_scalar, priv1, "x")); + TEST_FFI_OK(botan_pubkey_get_field, (public_x, pub1, "public_x")); + TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub1, "public_y")); + TEST_FFI_OK(botan_privkey_load_ecdh, (&loaded_privkey1, private_scalar, "secp256r1")); + TEST_FFI_OK(botan_pubkey_load_ecdh, (&loaded_pubkey1, public_x, public_y, "secp256r1")); + TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey1, rng, 0)); + TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey1, rng, 0)); + + ffi_test_pubkey_export(result, loaded_pubkey1, priv1, rng); ffi_test_pubkey_export(result, pub2, priv2, rng); botan_pk_op_ka_t ka1; - REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka1, priv1, "KDF2(SHA-256)", 0)); + REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka1, loaded_privkey1, "KDF2(SHA-256)", 0)); botan_pk_op_ka_t ka2; REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka2, priv2, "KDF2(SHA-256)", 0)); @@ -1333,13 +1349,17 @@ class FFI_Unit_Tests : public Test result.test_eq("shared ECDH key", key1, key2); + TEST_FFI_OK(botan_mp_destroy, (private_scalar)); + TEST_FFI_OK(botan_mp_destroy, (public_x)); + TEST_FFI_OK(botan_mp_destroy, (public_y)); TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka1)); TEST_FFI_OK(botan_pk_op_key_agreement_destroy, (ka2)); TEST_FFI_OK(botan_privkey_destroy, (priv1)); TEST_FFI_OK(botan_privkey_destroy, (priv2)); TEST_FFI_OK(botan_pubkey_destroy, (pub1)); TEST_FFI_OK(botan_pubkey_destroy, (pub2)); - + TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey1)); + TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey1)); return result; } |