diff options
author | Jack Lloyd <[email protected]> | 2017-04-04 09:15:10 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-04-04 09:15:10 -0400 |
commit | 274ecccd1784fb6cfee83ea5a0a6cbec31881c81 (patch) | |
tree | ccc37f0009658898e6e5e3fe181dace31f327fe4 | |
parent | 753b4c2d5301574d3c9390b79aa275a49809e6c8 (diff) | |
parent | faced4459edd144d0158f4908da75e8d649d43a1 (diff) |
Merge GH #964 Add various useful FFI functions for public key crypto
-rw-r--r-- | doc/manual/ffi.rst | 28 | ||||
-rw-r--r-- | src/lib/ffi/ffi.cpp | 356 | ||||
-rw-r--r-- | src/lib/ffi/ffi.h | 32 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 128 | ||||
-rw-r--r-- | src/tests/unit_tls.cpp | 2 |
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 } } |