aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-08-22 10:31:07 -0400
committerJack Lloyd <[email protected]>2017-08-22 10:31:07 -0400
commit94b7cc4a28e3d3318d3bf3949ea58f7a70f38535 (patch)
tree0bc74f4fa9eaac344c51a3a1e3f95433c952078a
parent4f2e19db300bc77672feb86925bcd7321ca4ed96 (diff)
parente6e8223149913badf8cc3ce06a06839c3f243f74 (diff)
Merge GH #1155 Add DH functions to FFI
-rw-r--r--doc/manual/ffi.rst17
-rw-r--r--src/lib/ffi/ffi.h36
-rw-r--r--src/lib/ffi/ffi_pkey_algs.cpp60
-rw-r--r--src/tests/test_ffi.cpp135
4 files changed, 240 insertions, 8 deletions
diff --git a/doc/manual/ffi.rst b/doc/manual/ffi.rst
index 89e075885..db3bd8d53 100644
--- a/doc/manual/ffi.rst
+++ b/doc/manual/ffi.rst
@@ -492,6 +492,8 @@ Public Key Creation, Import and Export
.. cpp:function:: int botan_privkey_create_mceliece(botan_privkey_t* key, botan_rng_t rng, size_t n, size_t t)
+.. cpp:function:: int botan_privkey_create_dh(botan_privkey_t* key, botan_rng_t rng, const char* params)
+
.. cpp:function:: int botan_privkey_load(botan_privkey_t* key, botan_rng_t rng, \
const uint8_t bits[], size_t len, \
const char* password)
@@ -638,7 +640,20 @@ ElGamal specific functions
.. 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.
+ Initialize a public ElGamal key using group parameters p and g and public key y.
+
+Diffie Hellmann specific functions
+----------------------------------------
+
+.. cpp:function:: int botan_privkey_load_dh(botan_privkey_t* key, \
+ botan_mp_t p, botan_mp_t g, botan_mp_t x)
+
+ Initialize a private Diffie Hellmann key using group parameters p and g and private key x.
+
+.. cpp:function:: int botan_pubkey_load_dh(botan_pubkey_t* key, \
+ botan_mp_t p, botan_mp_t g, botan_mp_t y)
+
+ Initialize a public Diffie Hellmann key using group parameters p and g and public key y.
Public Key Encryption/Decryption
----------------------------------------
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index f59da0545..565d5ce7b 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -693,6 +693,7 @@ BOTAN_DLL int botan_privkey_create_rsa(botan_privkey_t* key, botan_rng_t rng, si
BOTAN_DLL int botan_privkey_create_ecdsa(botan_privkey_t* key, botan_rng_t rng, const char* params);
BOTAN_DLL int botan_privkey_create_ecdh(botan_privkey_t* key, botan_rng_t rng, const char* params);
BOTAN_DLL int botan_privkey_create_mceliece(botan_privkey_t* key, botan_rng_t rng, size_t n, size_t t);
+BOTAN_DLL int botan_privkey_create_dh(botan_privkey_t* key, botan_rng_t rng, const char* param);
/*
* Input currently assumed to be PKCS #8 structure;
@@ -832,6 +833,41 @@ 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);
/*
+* Loads Diffie Hellman 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_dh(botan_privkey_t* key,
+ botan_mp_t p,
+ botan_mp_t g,
+ botan_mp_t x);
+/*
+* Loads Diffie Hellman 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_dh(botan_pubkey_t* key,
+ botan_mp_t p,
+ botan_mp_t g,
+ botan_mp_t y);
+
+/*
* Algorithm specific key operations: ElGamal
*/
diff --git a/src/lib/ffi/ffi_pkey_algs.cpp b/src/lib/ffi/ffi_pkey_algs.cpp
index 844a38846..bde673487 100644
--- a/src/lib/ffi/ffi_pkey_algs.cpp
+++ b/src/lib/ffi/ffi_pkey_algs.cpp
@@ -60,6 +60,11 @@
#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)
@@ -496,6 +501,61 @@ int botan_privkey_load_elgamal(botan_privkey_t* key,
#endif
}
+/* Diffie Hellman specific operations */
+
+int botan_privkey_create_dh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str)
+ {
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() {
+ if(key_obj == nullptr || rng_obj == nullptr || param_str == nullptr || *param_str == 0)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+ *key_obj = nullptr;
+
+ Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
+ Botan::DL_Group grp(param_str);
+ *key_obj = new botan_privkey_struct(new Botan::DH_PrivateKey(rng, grp, 0));
+ return BOTAN_FFI_SUCCESS;
+ });
+#else
+ BOTAN_UNUSED(key_obj, rng_obj, param_str);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+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, [=]() {
+ 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, [=]() {
+ 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)
diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp
index 34d832026..95fb75831 100644
--- a/src/tests/test_ffi.cpp
+++ b/src/tests/test_ffi.cpp
@@ -402,6 +402,10 @@ class FFI_Unit_Tests : public Test
results.push_back(ffi_test_elgamal(rng));
#endif
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ results.push_back(ffi_test_dh(rng));
+#endif
+
#if defined(BOTAN_HAS_ED25519)
results.push_back(ffi_test_ed25519(rng));
#endif
@@ -1588,15 +1592,14 @@ class FFI_Unit_Tests : public Test
botan_pk_op_ka_t ka2;
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka2, priv2, "KDF2(SHA-256)", 0));
- std::vector<uint8_t> pubkey1(256); // length problem again
- size_t pubkey1_len = pubkey1.size();
+ size_t pubkey1_len = 0;
+ TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pk_op_key_agreement_export_public, (priv1, nullptr, &pubkey1_len));
+ std::vector<uint8_t> pubkey1(pubkey1_len);
REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv1, pubkey1.data(), &pubkey1_len));
- pubkey1.resize(pubkey1_len);
-
- std::vector<uint8_t> pubkey2(256); // length problem again
- size_t pubkey2_len = pubkey2.size();
+ size_t pubkey2_len = 0;
+ TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pk_op_key_agreement_export_public, (priv2, nullptr, &pubkey2_len));
+ std::vector<uint8_t> pubkey2(pubkey2_len);
REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv2, pubkey2.data(), &pubkey2_len));
- pubkey2.resize(pubkey2_len);
std::vector<uint8_t> salt(32);
TEST_FFI_OK(botan_rng_get, (rng, salt.data(), salt.size()));
@@ -1824,6 +1827,124 @@ class FFI_Unit_Tests : public Test
}
+ Test::Result ffi_test_dh(botan_rng_t rng)
+ {
+ Test::Result result("FFI DH");
+
+ botan_mp_t private_x, public_g, public_p, public_y;
+
+ botan_privkey_t loaded_privkey1;
+ botan_pubkey_t loaded_pubkey1;
+
+ botan_mp_init(&private_x);
+
+ botan_mp_init(&public_g);
+ botan_mp_init(&public_p);
+ botan_mp_init(&public_y);
+
+ botan_privkey_t priv1;
+ REQUIRE_FFI_OK(botan_privkey_create_dh, (&priv1, rng, "modp/ietf/2048"));
+
+ botan_privkey_t priv2;
+ REQUIRE_FFI_OK(botan_privkey_create_dh, (&priv2, rng, "modp/ietf/2048"));
+
+ botan_pubkey_t pub1;
+ REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub1, priv1));
+
+ botan_pubkey_t pub2;
+ REQUIRE_FFI_OK(botan_privkey_export_pubkey, (&pub2, priv2));
+
+ // Reload key-pair1 in order to test functions for key loading
+ TEST_FFI_OK(botan_privkey_get_field, (private_x, priv1, "x"));
+ TEST_FFI_OK(botan_pubkey_get_field, (public_g, pub1, "g"));
+ TEST_FFI_OK(botan_pubkey_get_field, (public_p, pub1, "p"));
+ TEST_FFI_OK(botan_pubkey_get_field, (public_y, pub1, "y"));
+
+ TEST_FFI_OK(botan_privkey_load_dh, (&loaded_privkey1, public_p, public_g, private_x));
+
+ TEST_FFI_OK(botan_pubkey_load_dh, (&loaded_pubkey1, public_p, public_g, public_y));
+
+ TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey1, rng, 0));
+ TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey1, rng, 0));
+
+ botan_mp_t loaded_public_g, loaded_public_p, loaded_public_y;
+ botan_mp_init(&loaded_public_g);
+ botan_mp_init(&loaded_public_p);
+ botan_mp_init(&loaded_public_y);
+
+ TEST_FFI_OK(botan_pubkey_get_field, (loaded_public_g, loaded_pubkey1, "g"));
+ TEST_FFI_OK(botan_pubkey_get_field, (loaded_public_p, loaded_pubkey1, "p"));
+ TEST_FFI_OK(botan_pubkey_get_field, (loaded_public_y, loaded_pubkey1, "y"));
+
+ int cmp;
+
+ TEST_FFI_OK(botan_mp_cmp, (&cmp, loaded_public_g, public_g));
+ result.confirm("bigint_mp_cmp(g, g)", cmp == 0);
+
+ TEST_FFI_OK(botan_mp_cmp, (&cmp, loaded_public_p, public_p));
+ result.confirm("bigint_mp_cmp(p, p)", cmp == 0);
+
+ TEST_FFI_OK(botan_mp_cmp, (&cmp, loaded_public_y, public_y));
+ result.confirm("bigint_mp_cmp(y, y)", cmp == 0);
+
+ botan_pk_op_ka_t ka1;
+ REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka1, loaded_privkey1, "Raw", 0));
+ botan_pk_op_ka_t ka2;
+ REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka2, priv2, "Raw", 0));
+
+ size_t pubkey1_len = 0;
+ TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pk_op_key_agreement_export_public, (priv1, nullptr, &pubkey1_len));
+ std::vector<uint8_t> pubkey1(pubkey1_len);
+ REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv1, pubkey1.data(), &pubkey1_len));
+ size_t pubkey2_len = 0;
+ TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_pk_op_key_agreement_export_public, (priv2, nullptr, &pubkey2_len));
+ std::vector<uint8_t> pubkey2(pubkey2_len);
+ REQUIRE_FFI_OK(botan_pk_op_key_agreement_export_public, (priv2, pubkey2.data(), &pubkey2_len));
+
+ std::vector<uint8_t> salt(32);
+
+ TEST_FFI_OK(botan_rng_get, (rng, salt.data(), salt.size()));
+
+ const size_t shared_key_len = 256;
+
+ std::vector<uint8_t> key1(shared_key_len);
+ size_t key1_len = key1.size();
+
+ TEST_FFI_OK(botan_pk_op_key_agreement, (ka1, key1.data(), &key1_len,
+ pubkey2.data(), pubkey2.size(),
+ salt.data(), salt.size()));
+
+ std::vector<uint8_t> key2(shared_key_len);
+ size_t key2_len = key2.size();
+
+ TEST_FFI_OK(botan_pk_op_key_agreement, (ka2, key2.data(), &key2_len,
+ pubkey1.data(), pubkey1.size(),
+ salt.data(), salt.size()));
+
+ result.test_eq("shared DH key", key1, key2);
+
+ TEST_FFI_OK(botan_mp_destroy, (private_x));
+ TEST_FFI_OK(botan_mp_destroy, (public_p));
+ TEST_FFI_OK(botan_mp_destroy, (public_g));
+ TEST_FFI_OK(botan_mp_destroy, (public_y));
+
+ TEST_FFI_OK(botan_mp_destroy, (loaded_public_p));
+ TEST_FFI_OK(botan_mp_destroy, (loaded_public_g));
+ TEST_FFI_OK(botan_mp_destroy, (loaded_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;
+ }
+
+
};
BOTAN_REGISTER_TEST("ffi", FFI_Unit_Tests);