aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-04-15 11:38:00 -0400
committerJack Lloyd <[email protected]>2017-04-15 11:38:00 -0400
commitca72e257107fb17075ccad5eca264110bc46d572 (patch)
treeebff0c12f6b4051ce7bf6cc32540f1d3e5a3bd10
parentd0e4ce08973dbbc1ed28c85b67371e720e425922 (diff)
parent70f24fcccb832de6a0d2563306a82f306370033a (diff)
Merge GH #1008 Support ElGamal in FFI interface
-rw-r--r--doc/manual/ffi.rst12
-rw-r--r--src/lib/ffi/ffi.cpp52
-rw-r--r--src/lib/ffi/ffi.h41
-rw-r--r--src/tests/test_ffi.cpp76
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);