diff options
author | Jack Lloyd <[email protected]> | 2017-04-15 11:38:00 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-04-15 11:38:00 -0400 |
commit | ca72e257107fb17075ccad5eca264110bc46d572 (patch) | |
tree | ebff0c12f6b4051ce7bf6cc32540f1d3e5a3bd10 | |
parent | d0e4ce08973dbbc1ed28c85b67371e720e425922 (diff) | |
parent | 70f24fcccb832de6a0d2563306a82f306370033a (diff) |
Merge GH #1008 Support ElGamal in FFI interface
-rw-r--r-- | doc/manual/ffi.rst | 12 | ||||
-rw-r--r-- | src/lib/ffi/ffi.cpp | 52 | ||||
-rw-r--r-- | src/lib/ffi/ffi.h | 41 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 76 |
4 files changed, 180 insertions, 1 deletions
diff --git a/doc/manual/ffi.rst b/doc/manual/ffi.rst index 8acbf225a..61a06718a 100644 --- a/doc/manual/ffi.rst +++ b/doc/manual/ffi.rst @@ -623,6 +623,18 @@ DSA specific functions Initialize a private DSA key using group parameters p, q, and g and public key y. +ElGamal specific functions +---------------------------------------- + +.. cpp:function:: int botan_privkey_load_elgamal(botan_privkey_t* key, \ + botan_mp_t p, botan_mp_t g, botan_mp_t x) + + Initialize a private ElGamal key using group parameters p and g and private key x. + +.. cpp:function:: int botan_pubkey_load_elgamal(botan_pubkey_t* key, \ + botan_mp_t p, botan_mp_t g, botan_mp_t y) + + Initialize a private ElGamal key using group parameters p and g and public key y. Public Key Encryption/Decryption ---------------------------------------- diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp index 7cf69efb3..8e341d83d 100644 --- a/src/lib/ffi/ffi.cpp +++ b/src/lib/ffi/ffi.cpp @@ -26,6 +26,7 @@ #include <botan/reducer.h> #include <botan/numthry.h> #include <botan/divide.h> +#include <botan/elgamal.h> #include <cstring> #include <memory> @@ -1422,6 +1423,57 @@ int botan_pubkey_load_dsa(botan_pubkey_t* key, #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; + try + { + Botan::DL_Group group(safe_get(p), safe_get(g)); + *key = new botan_pubkey_struct(new Botan::ElGamal_PublicKey(group, safe_get(y))); + return 0; + } + catch(std::exception& exn) + { + log_exception(BOTAN_CURRENT_FUNCTION, exn.what()); + } + + return -1; +#else + BOTAN_UNUSED(p); + BOTAN_UNUSED(q); + BOTAN_UNUSED(g); + BOTAN_UNUSED(x); + 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; + try + { + 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 0; + } + catch(std::exception& e) + { + log_exception(BOTAN_CURRENT_FUNCTION, e.what()); + } + return -1; +#else + BOTAN_UNUSED(p); + BOTAN_UNUSED(g); + BOTAN_UNUSED(x); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + namespace { Botan::BigInt botan_pubkey_do_get_field(const Botan::Public_Key& key, diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h index 59e767385..8fb7ca832 100644 --- a/src/lib/ffi/ffi.h +++ b/src/lib/ffi/ffi.h @@ -175,7 +175,7 @@ typedef struct botan_rng_struct* botan_rng_t; * "system": System_RNG, "user": AutoSeeded_RNG * Set rng_type to null or empty string to let the library choose * -* TODO: replace rng_type with simple flags? +* TODO: replace rng_type with simple flags? */ BOTAN_DLL int botan_rng_init(botan_rng_t* rng, const char* rng_type); @@ -785,6 +785,45 @@ BOTAN_DLL int botan_pubkey_dsa_get_g(botan_mp_t d, botan_pubkey_t key); BOTAN_DLL int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key); /* +* Algorithm specific key operations: ElGamal +*/ + +/* +* Loads ElGamal public key +* @param key variable populated with key material +* @param p prime order of a Z_p group +* @param g group generator +* @param y public key +* +* @pre key is NULL on input +* @post function allocates memory and assigns to `key' +* +* @return 0 on success, a negative value on failure +*/ +BOTAN_DLL int botan_pubkey_load_elgamal(botan_pubkey_t* key, + botan_mp_t p, + botan_mp_t g, + botan_mp_t y); + +/* +* Loads ElGamal private key +* +* @param key variable populated with key material +* @param p prime order of a Z_p group +* @param g group generator +* @param x private key +* +* @pre key is NULL on input +* @post function allocates memory and assigns to `key' +* +* @return 0 on success, a negative value on failure +*/ +BOTAN_DLL int botan_privkey_load_elgamal(botan_privkey_t* key, + botan_mp_t p, + botan_mp_t g, + botan_mp_t x); + +/* * Public Key Encryption */ typedef struct botan_pk_op_encrypt_struct* botan_pk_op_encrypt_t; diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp index c84dfd224..06ed21904 100644 --- a/src/tests/test_ffi.cpp +++ b/src/tests/test_ffi.cpp @@ -409,6 +409,10 @@ class FFI_Unit_Tests : public Test results.push_back(ffi_test_mceliece(rng)); #endif +#if defined(BOTAN_HAS_ELGAMAL) + results.push_back(ffi_test_elgamal(rng)); +#endif + TEST_FFI_OK(botan_rng_destroy, (rng)); results.push_back(result); @@ -1151,6 +1155,78 @@ class FFI_Unit_Tests : public Test return result; } + + Test::Result ffi_test_elgamal(botan_rng_t rng) + { + Test::Result result("FFI ELGAMAL"); + + botan_privkey_t priv; + + if(TEST_FFI_OK(botan_privkey_create, (&priv, "ElGamal", nullptr, rng))) + { + TEST_FFI_OK(botan_privkey_check_key, (priv, rng, 0)); + + botan_pubkey_t pub; + TEST_FFI_OK(botan_privkey_export_pubkey, (&pub, priv)); + TEST_FFI_OK(botan_pubkey_check_key, (pub, rng, 0)); + + ffi_test_pubkey_export(result, pub, priv, rng); + botan_mp_t p, g, x, y; + botan_mp_init(&p); + botan_mp_init(&g); + botan_mp_init(&x); + botan_mp_init(&y); + + TEST_FFI_OK(botan_pubkey_get_field, (p, pub, "p")); + TEST_FFI_OK(botan_pubkey_get_field, (g, pub, "g")); + TEST_FFI_OK(botan_pubkey_get_field, (y, pub, "y")); + TEST_FFI_OK(botan_privkey_get_field,(x, priv,"x")); + + size_t p_len = 0; + TEST_FFI_OK(botan_mp_num_bytes, (p, &p_len)); + + botan_privkey_t loaded_privkey; + TEST_FFI_OK(botan_privkey_load_elgamal, (&loaded_privkey, p, g, x)); + TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0)); + + botan_pubkey_t loaded_pubkey; + TEST_FFI_OK(botan_pubkey_load_elgamal, (&loaded_pubkey, p, g, y)); + TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0)); + + botan_mp_destroy(p); + botan_mp_destroy(g); + botan_mp_destroy(y); + botan_mp_destroy(x); + + + std::vector<uint8_t> plaintext(16, 0xFF); + std::vector<uint8_t> ciphertext(p_len*2, 0); + std::vector<uint8_t> decryption(16, 0); + + // Test encryption + botan_pk_op_encrypt_t op_enc; + size_t ct_len = ciphertext.size(); + REQUIRE_FFI_OK(botan_pk_op_encrypt_create, (&op_enc, loaded_pubkey, "Raw", 0)); + TEST_FFI_OK(botan_pk_op_encrypt, (op_enc, rng, ciphertext.data(), &ct_len, plaintext.data(), plaintext.size())); + TEST_FFI_OK(botan_pk_op_encrypt_destroy, (op_enc)); + + // Test decryption + botan_pk_op_decrypt_t op_dec; + size_t pt_len = decryption.size(); + REQUIRE_FFI_OK(botan_pk_op_decrypt_create, (&op_dec, loaded_privkey, "Raw", 0)); + TEST_FFI_OK(botan_pk_op_decrypt, (op_dec, decryption.data(), &pt_len, ciphertext.data(), ct_len)); + TEST_FFI_OK(botan_pk_op_decrypt_destroy, (op_dec)); + + TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey)); + TEST_FFI_OK(botan_pubkey_destroy, (pub)); + TEST_FFI_OK(botan_privkey_destroy, (loaded_privkey)); + TEST_FFI_OK(botan_privkey_destroy, (priv)); + } + + return result; + } + + }; BOTAN_REGISTER_TEST("ffi", FFI_Unit_Tests); |