diff options
author | Jack Lloyd <[email protected]> | 2017-08-22 10:31:07 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-08-22 10:31:07 -0400 |
commit | 94b7cc4a28e3d3318d3bf3949ea58f7a70f38535 (patch) | |
tree | 0bc74f4fa9eaac344c51a3a1e3f95433c952078a | |
parent | 4f2e19db300bc77672feb86925bcd7321ca4ed96 (diff) | |
parent | e6e8223149913badf8cc3ce06a06839c3f243f74 (diff) |
Merge GH #1155 Add DH functions to FFI
-rw-r--r-- | doc/manual/ffi.rst | 17 | ||||
-rw-r--r-- | src/lib/ffi/ffi.h | 36 | ||||
-rw-r--r-- | src/lib/ffi/ffi_pkey_algs.cpp | 60 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 135 |
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); |