diff options
-rw-r--r-- | src/lib/ffi/ffi.h | 8 | ||||
-rw-r--r-- | src/lib/ffi/ffi_pkey_algs.cpp | 49 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 17 |
3 files changed, 74 insertions, 0 deletions
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h index 323bf54de..c1b1a1284 100644 --- a/src/lib/ffi/ffi.h +++ b/src/lib/ffi/ffi.h @@ -829,12 +829,20 @@ BOTAN_PUBLIC_API(2,0) int botan_privkey_load_rsa(botan_privkey_t* key, botan_mp_t q, botan_mp_t e); +BOTAN_PUBLIC_API(2,0) int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, + const uint8_t bits[], + size_t len); + BOTAN_PUBLIC_API(2,0) int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t rsa_key); BOTAN_PUBLIC_API(2,0) int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t rsa_key); BOTAN_PUBLIC_API(2,0) int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t rsa_key); BOTAN_PUBLIC_API(2,0) int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t rsa_key); BOTAN_PUBLIC_API(2,0) int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t rsa_key); +BOTAN_PUBLIC_API(2,0) int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, + uint8_t out[], size_t* out_len, + uint32_t flags); + BOTAN_PUBLIC_API(2,0) int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e); diff --git a/src/lib/ffi/ffi_pkey_algs.cpp b/src/lib/ffi/ffi_pkey_algs.cpp index 7fa06b71b..46c7e28d5 100644 --- a/src/lib/ffi/ffi_pkey_algs.cpp +++ b/src/lib/ffi/ffi_pkey_algs.cpp @@ -1,12 +1,14 @@ /* * (C) 2015,2017 Jack Lloyd * (C) 2017 Ribose Inc +* (C) 2018 René Korthaus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ #include <botan/ffi.h> #include <botan/hash.h> +#include <botan/pem.h> #include <botan/internal/ffi_util.h> #include <botan/internal/ffi_pkey.h> #include <botan/internal/ffi_rng.h> @@ -282,6 +284,26 @@ int botan_privkey_load_rsa(botan_privkey_t* key, #endif } +int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key, + const uint8_t bits[], + size_t len) + { +#if defined(BOTAN_HAS_RSA) + *key = nullptr; + + Botan::secure_vector<uint8_t> src(bits, bits + len); + return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() -> int { + *key = new botan_privkey_struct(new Botan::RSA_PrivateKey(Botan::AlgorithmIdentifier("RSA", + Botan::AlgorithmIdentifier::USE_NULL_PARAM), + src)); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(key, bits, len); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + int botan_pubkey_load_rsa(botan_pubkey_t* key, botan_mp_t n, botan_mp_t e) { @@ -332,6 +354,33 @@ int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key) return botan_pubkey_get_field(n, key, "n"); } +int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key, + uint8_t out[], size_t* out_len, + uint32_t flags) + { +#if defined(BOTAN_HAS_RSA) + return BOTAN_FFI_DO(Botan::Private_Key, rsa_key, k, { + if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<const Botan::RSA_PrivateKey*>(&k)) + { + if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER) + return write_vec_output(out, out_len, rsa->private_key_bits()); + else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM) + return write_str_output(out, out_len, Botan::PEM_Code::encode(rsa->private_key_bits(), + "RSA PRIVATE KEY")); + else + return BOTAN_FFI_ERROR_BAD_FLAG; + } + else + { + return BOTAN_FFI_ERROR_BAD_PARAMETER; + } + }); +#else + BOTAN_UNUSED(rsa_key, out, out_len); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif + } + /* DSA specific operations */ int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t pbits, size_t qbits) { diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp index 9eb7847a2..45a5f0139 100644 --- a/src/tests/test_ffi.cpp +++ b/src/tests/test_ffi.cpp @@ -1313,6 +1313,23 @@ class FFI_Unit_Tests final : public Test botan_mp_destroy(e); botan_mp_destroy(n); + size_t pkcs1_len = 0; + TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, + botan_privkey_rsa_get_privkey, (loaded_privkey, nullptr, &pkcs1_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER)); + + std::vector<uint8_t> pkcs1(pkcs1_len); + TEST_FFI_OK(botan_privkey_rsa_get_privkey, (loaded_privkey, pkcs1.data(), &pkcs1_len, BOTAN_PRIVKEY_EXPORT_FLAG_DER)); + + botan_privkey_t privkey_from_pkcs1; + TEST_FFI_OK(botan_privkey_load_rsa_pkcs1, (&privkey_from_pkcs1, pkcs1.data(), pkcs1_len)); + TEST_FFI_OK(botan_privkey_destroy, (privkey_from_pkcs1)); + + pkcs1_len = 0; + TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, + botan_privkey_rsa_get_privkey, (loaded_privkey, nullptr, &pkcs1_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM)); + pkcs1.resize(pkcs1_len); + TEST_FFI_OK(botan_privkey_rsa_get_privkey, (loaded_privkey, pkcs1.data(), &pkcs1_len, BOTAN_PRIVKEY_EXPORT_FLAG_PEM)); + char namebuf[32] = { 0 }; size_t name_len = sizeof(namebuf); if(TEST_FFI_OK(botan_pubkey_algo_name, (loaded_pubkey, namebuf, &name_len))) |