aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-04-04 09:15:10 -0400
committerJack Lloyd <[email protected]>2017-04-04 09:15:10 -0400
commit274ecccd1784fb6cfee83ea5a0a6cbec31881c81 (patch)
treeccc37f0009658898e6e5e3fe181dace31f327fe4
parent753b4c2d5301574d3c9390b79aa275a49809e6c8 (diff)
parentfaced4459edd144d0158f4908da75e8d649d43a1 (diff)
Merge GH #964 Add various useful FFI functions for public key crypto
-rw-r--r--doc/manual/ffi.rst28
-rw-r--r--src/lib/ffi/ffi.cpp356
-rw-r--r--src/lib/ffi/ffi.h32
-rw-r--r--src/tests/test_ffi.cpp128
-rw-r--r--src/tests/unit_tls.cpp2
5 files changed, 465 insertions, 81 deletions
diff --git a/doc/manual/ffi.rst b/doc/manual/ffi.rst
index f5f004624..5cf0dbac5 100644
--- a/doc/manual/ffi.rst
+++ b/doc/manual/ffi.rst
@@ -510,6 +510,21 @@ Public Key Creation, Import and Export
.. cpp:function:: int botan_pubkey_destroy(botan_pubkey_t key)
+.. cpp:function:: int botan_pubkey_get_field(botan_mp_t output, \
+ botan_pubkey_t key, \
+ const char* field_name)
+
+ Read an algorithm specific field from the public key object, placing it into output.
+ For exampe "n" or "e" for RSA keys or "p", "q", "g", and "y" for DSA keys.
+
+.. cpp:function:: int botan_privkey_get_field(botan_mp_t output, \
+ botan_privkey_t key, \
+ const char* field_name)
+
+ Read an algorithm specific field from the private key object, placing it into output.
+ For exampe "p" or "q" for RSA keys, or "x" for DSA keys or ECC keys.
+
+
RSA specific functions
----------------------------------------
@@ -551,6 +566,19 @@ RSA specific functions
Initialize a public RSA key using parameters n and e.
+DSA specific functions
+----------------------------------------
+
+.. cpp:function:: int botan_privkey_load_dsa(botan_privkey_t* key, \
+ botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t x)
+
+ Initialize a private DSA key using group parameters p, q, and g and private key x.
+
+.. cpp:function:: int botan_pubkey_load_dsa(botan_pubkey_t* key, \
+ botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t y)
+
+ Initialize a private DSA key using group parameters p, q, 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 37664daa3..945eacaf8 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -32,10 +32,22 @@
#include <botan/rsa.h>
#endif
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa.h>
+#endif
+
#if defined(BOTAN_HAS_ECDSA)
#include <botan/ecdsa.h>
#endif
+#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
+ #include <botan/ecc_key.h>
+#endif
+
+#if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY)
+ #include <botan/dl_algo.h>
+#endif
+
#if defined(BOTAN_HAS_ECDH)
#include <botan/ecdh.h>
#endif
@@ -1028,20 +1040,31 @@ int botan_privkey_create(botan_privkey_t* key_obj,
{
try
{
- if(key_obj == nullptr || rng_obj == nullptr)
- return -1;
+ if(key_obj == nullptr)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+ *key_obj = nullptr;
+ if(rng_obj == nullptr)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
if(algo_name == nullptr)
algo_name = "RSA";
if(algo_params == nullptr)
algo_params = "";
- *key_obj = nullptr;
-
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
std::unique_ptr<Botan::Private_Key> key(
Botan::create_private_key(algo_name, rng, algo_params));
- *key_obj = new botan_privkey_struct(key.release());
- return 0;
+
+ if(key)
+ {
+ *key_obj = new botan_privkey_struct(key.release());
+ return 0;
+ }
+ else
+ {
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+ }
}
catch(std::exception& e)
{
@@ -1199,6 +1222,30 @@ int botan_privkey_load(botan_privkey_t* key, botan_rng_t rng_obj,
return -1;
}
+int botan_pubkey_load(botan_pubkey_t* key,
+ const uint8_t bits[], size_t bits_len)
+ {
+ *key = nullptr;
+
+ try
+ {
+ Botan::DataSource_Memory src(bits, bits_len);
+ std::unique_ptr<Botan::Public_Key> pubkey(Botan::X509::load_key(src));
+
+ if(pubkey)
+ {
+ *key = new botan_pubkey_struct(pubkey.release());
+ return 0;
+ }
+ }
+ catch(std::exception& e)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, e.what());
+ }
+
+ return -1;
+ }
+
int botan_privkey_load_rsa(botan_privkey_t* key,
botan_mp_t p, botan_mp_t q, botan_mp_t d)
{
@@ -1244,117 +1291,264 @@ int botan_pubkey_load_rsa(botan_pubkey_t* key,
#endif
}
-int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key)
+int botan_privkey_load_dsa(botan_privkey_t* key,
+ botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t x)
{
-#if defined(BOTAN_HAS_RSA)
- return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
- if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<Botan::RSA_PrivateKey*>(&k))
- {
- safe_get(p) = rsa->get_p();
- }
- else
- throw FFI_Error("Passed non-RSA key to botan_privkey_rsa_get_p");
- });
+ *key = nullptr;
+
+#if defined(BOTAN_HAS_DSA)
+ try
+ {
+ Botan::Null_RNG null_rng;
+ Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
+ *key = new botan_privkey_struct(new Botan::DSA_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(q);
+ BOTAN_UNUSED(g);
+ BOTAN_UNUSED(x);
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
#endif
}
-int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key)
+int botan_pubkey_load_dsa(botan_pubkey_t* key,
+ botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t y)
{
-#if defined(BOTAN_HAS_RSA)
- return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
- if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<Botan::RSA_PrivateKey*>(&k))
- {
- safe_get(q) = rsa->get_q();
- }
- else
- throw FFI_Error("Passed non-RSA key to botan_privkey_rsa_get_q");
- });
+ *key = nullptr;
+
+#if defined(BOTAN_HAS_DSA)
+ try
+ {
+ Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g));
+ *key = new botan_pubkey_struct(new Botan::DSA_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(y);
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
#endif
}
-int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key)
+namespace {
+
+Botan::BigInt botan_pubkey_do_get_field(const Botan::Public_Key& key,
+ const std::string& field)
{
+ // Maybe this should be `return key.get_integer_field(field_name)`?
+
#if defined(BOTAN_HAS_RSA)
- return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
- if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<Botan::RSA_PrivateKey*>(&k))
- {
- safe_get(n) = rsa->get_n();
- }
+ if(const Botan::RSA_PublicKey* rsa = dynamic_cast<const Botan::RSA_PublicKey*>(&key))
+ {
+ if(field == "n")
+ return rsa->get_n();
+ else if(field == "e")
+ return rsa->get_e();
else
- throw FFI_Error("Passed non-RSA key to botan_privkey_rsa_get_n");
- });
-#else
- return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+ throw Botan::Exception("Field not supported");
+ }
+#endif
+
+#if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY)
+ // Handles DSA, ElGamal, etc
+ if(const Botan::DL_Scheme_PublicKey* dl = dynamic_cast<const Botan::DL_Scheme_PublicKey*>(&key))
+ {
+ if(field == "p")
+ return dl->group_p();
+ else if(field == "q")
+ return dl->group_q();
+ else if(field == "g")
+ return dl->group_g();
+ else if(field == "y")
+ return dl->get_y();
+ else
+ throw Botan::Exception("Field not supported");
+ }
#endif
+
+#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
+ if(const Botan::EC_PublicKey* ecc = dynamic_cast<const Botan::EC_PublicKey*>(&key))
+ {
+ if(field == "public_x")
+ return ecc->public_point().get_affine_x();
+ else if(field == "public_y")
+ return ecc->public_point().get_affine_y();
+ else if(field == "base_x")
+ return ecc->domain().get_base_point().get_affine_x();
+ else if(field == "base_y")
+ return ecc->domain().get_base_point().get_affine_y();
+ else if(field == "p")
+ return ecc->domain().get_curve().get_p();
+ else if(field == "a")
+ return ecc->domain().get_curve().get_a();
+ else if(field == "b")
+ return ecc->domain().get_curve().get_b();
+ else if(field == "cofactor")
+ return ecc->domain().get_cofactor();
+ else if(field == "order")
+ return ecc->domain().get_order();
+ else
+ throw Botan::Exception("Field not supported");
+ }
+#endif
+
+ // Some other algorithm type not supported by this function
+ throw Botan::Exception("Unsupported algorithm type for botan_pubkey_get_field");
}
-int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key)
+Botan::BigInt botan_privkey_do_get_field(const Botan::Private_Key& key,
+ const std::string& field)
{
+ //return key.get_integer_field(field);
+
#if defined(BOTAN_HAS_RSA)
- return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
- if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<Botan::RSA_PrivateKey*>(&k))
- {
- safe_get(e) = rsa->get_e();
- }
+
+ if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&key))
+ {
+ if(field == "p")
+ return rsa->get_p();
+ else if(field == "q")
+ return rsa->get_q();
+ else if(field == "d")
+ return rsa->get_d();
+ else if(field == "c")
+ return rsa->get_c();
+ else if(field == "d1")
+ return rsa->get_d1();
+ else if(field == "d2")
+ return rsa->get_d2();
else
- throw FFI_Error("Passed non-RSA key to botan_privkey_rsa_get_e");
- });
-#else
- return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+ return botan_pubkey_do_get_field(key, field);
+ }
+#endif
+
+#if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY)
+ // Handles DSA, ElGamal, etc
+ if(const Botan::DL_Scheme_PrivateKey* dl = dynamic_cast<const Botan::DL_Scheme_PrivateKey*>(&key))
+ {
+ if(field == "x")
+ return dl->get_x();
+ else
+ return botan_pubkey_do_get_field(key, field);
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
+ if(const Botan::EC_PrivateKey* ecc = dynamic_cast<const Botan::EC_PrivateKey*>(&key))
+ {
+ if(field == "x")
+ return ecc->private_value();
+ else
+ return botan_pubkey_do_get_field(key, field);
+ }
#endif
+
+ // Some other algorithm type not supported by this function
+ throw Botan::Exception("Unsupported algorithm type for botan_privkey_get_field");
}
-int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key)
+}
+
+int botan_pubkey_get_field(botan_mp_t output,
+ botan_pubkey_t key,
+ const char* field_name_cstr)
{
-#if defined(BOTAN_HAS_RSA)
+ if(field_name_cstr == nullptr)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+ const std::string field_name(field_name_cstr);
+
+ return BOTAN_FFI_DO(Botan::Public_Key, key, k, {
+ safe_get(output) = botan_pubkey_do_get_field(k, field_name);
+ });
+ }
+
+int botan_privkey_get_field(botan_mp_t output,
+ botan_privkey_t key,
+ const char* field_name_cstr)
+ {
+ if(field_name_cstr == nullptr)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+ const std::string field_name(field_name_cstr);
+
return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
- if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<Botan::RSA_PrivateKey*>(&k))
- {
- safe_get(d) = rsa->get_e();
- }
- else
- throw FFI_Error("Passed non-RSA key to botan_privkey_rsa_get_d");
+ safe_get(output) = botan_privkey_do_get_field(k, field_name);
});
-#else
- return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
-#endif
+ }
+
+int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key)
+ {
+ return botan_privkey_get_field(p, key, "p");
+ }
+
+int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key)
+ {
+ return botan_privkey_get_field(q, key, "q");
+ }
+
+int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key)
+ {
+ return botan_privkey_get_field(n, key, "n");
+ }
+
+int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key)
+ {
+ return botan_privkey_get_field(e, key, "e");
+ }
+
+int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key)
+ {
+ return botan_privkey_get_field(d, key, "d");
}
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key)
{
-#if defined(BOTAN_HAS_RSA)
- return BOTAN_FFI_DO(Botan::Public_Key, key, k, {
- if(const Botan::RSA_PublicKey* rsa = dynamic_cast<Botan::RSA_PublicKey*>(&k))
- {
- safe_get(e) = rsa->get_e();
- }
- else
- throw FFI_Error("Passed non-RSA key to botan_pubkey_rsa_get_e");
- });
-#else
- return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
-#endif
+ return botan_pubkey_get_field(e, key, "e");
}
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key)
{
-#if defined(BOTAN_HAS_RSA)
- return BOTAN_FFI_DO(Botan::Public_Key, key, k, {
- if(const Botan::RSA_PublicKey* rsa = dynamic_cast<Botan::RSA_PublicKey*>(&k))
- {
- safe_get(n) = rsa->get_n();
- }
- else
- throw FFI_Error("Passed non-RSA key to botan_pubkey_rsa_get_n");
- });
-#else
- return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
-#endif
+ return botan_pubkey_get_field(n, key, "n");
+ }
+
+int botan_privkey_dsa_get_x(botan_mp_t x, botan_privkey_t key)
+ {
+ return botan_privkey_get_field(x, key, "x");
+ }
+
+int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key)
+ {
+ return botan_pubkey_get_field(p, key, "p");
+ }
+int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key)
+ {
+ return botan_pubkey_get_field(q, key, "q");
+ }
+int botan_pubkey_dsa_get_g(botan_mp_t g, botan_pubkey_t key)
+ {
+ return botan_pubkey_get_field(g, key, "g");
}
+int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key)
+ {
+ return botan_pubkey_get_field(y, key, "y");
+ }
+
int botan_privkey_destroy(botan_privkey_t key)
{
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index 3d62bb8c0..0901c4d4d 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -683,6 +683,16 @@ BOTAN_DLL int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash,
BOTAN_DLL int botan_pubkey_destroy(botan_pubkey_t key);
+/*
+* Get arbitrary named fields from public or privat keys
+*/
+BOTAN_DLL int botan_pubkey_get_field(botan_mp_t output,
+ botan_pubkey_t key,
+ const char* field_name);
+
+BOTAN_DLL int botan_privkey_get_field(botan_mp_t output,
+ botan_privkey_t key,
+ const char* field_name);
/*
* Algorithm specific key operations: RSA
@@ -706,6 +716,28 @@ BOTAN_DLL int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t rsa_key);
BOTAN_DLL int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t rsa_key);
/*
+* Algorithm specific key operations: DSA
+*/
+BOTAN_DLL int botan_privkey_load_dsa(botan_privkey_t* key,
+ botan_mp_t p,
+ botan_mp_t q,
+ botan_mp_t g,
+ botan_mp_t x);
+
+BOTAN_DLL int botan_pubkey_load_dsa(botan_pubkey_t* key,
+ botan_mp_t p,
+ botan_mp_t q,
+ botan_mp_t g,
+ botan_mp_t y);
+
+BOTAN_DLL int botan_privkey_dsa_get_x(botan_mp_t n, botan_privkey_t key);
+
+BOTAN_DLL int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key);
+BOTAN_DLL int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key);
+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);
+
+/*
* 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 4db0607f2..eee5fc39d 100644
--- a/src/tests/test_ffi.cpp
+++ b/src/tests/test_ffi.cpp
@@ -387,10 +387,26 @@ class FFI_Unit_Tests : public Test
std::vector<Test::Result> results;
results.push_back(ffi_test_mp(rng));
+
+#if defined(BOTAN_HAS_RSA)
results.push_back(ffi_test_rsa(rng));
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ results.push_back(ffi_test_dsa(rng));
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
results.push_back(ffi_test_ecdsa(rng));
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
results.push_back(ffi_test_ecdh(rng));
+#endif
+
+#if defined(BOTAN_HAS_MCELIECE)
results.push_back(ffi_test_mceliece(rng));
+#endif
TEST_FFI_OK(botan_rng_destroy, (rng));
@@ -622,6 +638,11 @@ class FFI_Unit_Tests : public Test
pubkey.resize(pubkey_len);
TEST_FFI_OK(botan_pubkey_export, (pub, pubkey.data(), &pubkey_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM));
+ // reimport exported public key
+ botan_pubkey_t pub_copy;
+ TEST_FFI_OK(botan_pubkey_load, (&pub_copy, pubkey.data(), pubkey_len));
+ TEST_FFI_OK(botan_pubkey_check_key, (pub_copy, rng, 0));
+
// export private key
std::vector<uint8_t> privkey;
size_t privkey_len = 0;
@@ -678,6 +699,7 @@ class FFI_Unit_Tests : public Test
Test::Result result("FFI RSA");
botan_privkey_t priv;
+
if(TEST_FFI_OK(botan_privkey_create_rsa, (&priv, rng, 1024)))
{
TEST_FFI_OK(botan_privkey_check_key, (priv, rng, 0));
@@ -798,6 +820,112 @@ class FFI_Unit_Tests : public Test
return result;
}
+ Test::Result ffi_test_dsa(botan_rng_t rng)
+ {
+ Test::Result result("FFI DSA");
+
+ botan_privkey_t priv;
+
+ if(TEST_FFI_OK(botan_privkey_create, (&priv, "DSA", "dsa/jce/1024", 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, q, g, x, y;
+ botan_mp_init(&p);
+ botan_mp_init(&q);
+ botan_mp_init(&g);
+ botan_mp_init(&x);
+ botan_mp_init(&y);
+
+ TEST_FFI_OK(botan_privkey_dsa_get_x, (x, priv));
+ TEST_FFI_OK(botan_pubkey_dsa_get_g, (g, pub));
+ TEST_FFI_OK(botan_pubkey_dsa_get_p, (p, pub));
+ TEST_FFI_OK(botan_pubkey_dsa_get_q, (q, pub));
+ TEST_FFI_OK(botan_pubkey_dsa_get_y, (y, pub));
+
+ botan_mp_t cmp;
+ botan_mp_init(&cmp);
+ TEST_FFI_OK(botan_privkey_get_field, (cmp, priv, "x"));
+ TEST_FFI_RC(1, botan_mp_equal, (cmp, x));
+ TEST_FFI_OK(botan_privkey_get_field, (cmp, priv, "y"));
+ TEST_FFI_RC(1, botan_mp_equal, (cmp, y));
+ TEST_FFI_OK(botan_privkey_get_field, (cmp, priv, "p"));
+ TEST_FFI_RC(1, botan_mp_equal, (cmp, p));
+ botan_mp_destroy(cmp);
+
+ botan_privkey_t loaded_privkey;
+ TEST_FFI_OK(botan_privkey_load_dsa, (&loaded_privkey, p, q, g, x));
+ TEST_FFI_OK(botan_privkey_check_key, (loaded_privkey, rng, 0));
+
+ botan_pubkey_t loaded_pubkey;
+ TEST_FFI_OK(botan_pubkey_load_dsa, (&loaded_pubkey, p, q, g, y));
+ TEST_FFI_OK(botan_pubkey_check_key, (loaded_pubkey, rng, 0));
+
+ botan_mp_destroy(p);
+ botan_mp_destroy(q);
+ botan_mp_destroy(g);
+ botan_mp_destroy(y);
+ botan_mp_destroy(x);
+
+ botan_pk_op_sign_t signer;
+
+ std::vector<uint8_t> message(6, 6);
+ std::vector<uint8_t> signature(20*2);
+
+ if(TEST_FFI_OK(botan_pk_op_sign_create, (&signer, loaded_privkey, "EMSA1(SHA-256)", 0)))
+ {
+ // TODO: break input into multiple calls to update
+ TEST_FFI_OK(botan_pk_op_sign_update, (signer, message.data(), message.size()));
+
+ signature.resize(20*2); // TODO: no way to derive this from API
+ size_t sig_len = signature.size();
+ TEST_FFI_OK(botan_pk_op_sign_finish, (signer, rng, signature.data(), &sig_len));
+ signature.resize(sig_len);
+
+ TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
+ }
+
+ botan_pk_op_verify_t verifier;
+
+ if(TEST_FFI_OK(botan_pk_op_verify_create, (&verifier, pub, "EMSA1(SHA-256)", 0)))
+ {
+ TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
+ TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
+
+ // TODO: randomize this
+ signature[0] ^= 1;
+ TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
+ TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
+
+ message[0] ^= 1;
+ TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
+ TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
+
+ signature[0] ^= 1;
+ TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
+ TEST_FFI_FAIL("bad signature", botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
+
+ message[0] ^= 1;
+ TEST_FFI_OK(botan_pk_op_verify_update, (verifier, message.data(), message.size()));
+ TEST_FFI_OK(botan_pk_op_verify_finish, (verifier, signature.data(), signature.size()));
+
+ TEST_FFI_OK(botan_pk_op_verify_destroy, (verifier));
+ }
+
+ 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;
+ }
Test::Result ffi_test_ecdsa(botan_rng_t rng)
{
Test::Result result("FFI ECDSA");
diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp
index 77aebce93..28152e624 100644
--- a/src/tests/unit_tls.cpp
+++ b/src/tests/unit_tls.cpp
@@ -132,6 +132,8 @@ class Credentials_Manager_Test : public Botan::Credentials_Manager
chain.push_back(*m_dsa_ca);
break;
}
+#else
+ BOTAN_UNUSED(context);
#endif
}
}