From 1c741ad8d518260f3005a155832a583304849cee Mon Sep 17 00:00:00 2001 From: Nickolay Olshevsky Date: Thu, 19 Oct 2023 13:23:56 +0300 Subject: [PATCH] Refactor some of the CLI functions to use C++ FFI wrappers. --- src/rnp/fficli.cpp | 164 +++++++++++++++++---------------------------- src/rnp/fficli.h | 10 +-- 2 files changed, 65 insertions(+), 109 deletions(-) diff --git a/src/rnp/fficli.cpp b/src/rnp/fficli.cpp index 21146a1ed6..209a736791 100644 --- a/src/rnp/fficli.cpp +++ b/src/rnp/fficli.cpp @@ -814,76 +814,41 @@ cli_rnp_t::set_defkey() } bool -cli_rnp_t::is_cv25519_subkey(rnp_key_handle_t handle) +cli_rnp_t::is_cv25519_subkey(rnpffi::Key &key) { - bool primary = false; - if (rnp_key_is_primary(handle, &primary)) { - ERR_MSG("Error: failed to check for subkey."); - return false; - } - if (primary) { - return false; - } - char *alg = NULL; - if (rnp_key_get_alg(handle, &alg)) { - ERR_MSG("Error: failed to check key's alg."); - return false; - } - bool ecdh = !strcmp(alg, RNP_ALGNAME_ECDH); - rnp_buffer_destroy(alg); - if (!ecdh) { - return false; - } - char *curve = NULL; - if (rnp_key_get_curve(handle, &curve)) { - ERR_MSG("Error: failed to check key's curve."); + try { + if (key.is_primary()) { + return false; + } + if (strcmp(key.alg().c_str(), RNP_ALGNAME_ECDH)) { + return false; + } + return !strcmp(key.curve().c_str(), "Curve25519"); + } catch (const rnpffi::ffi_exception &e) { + ERR_MSG("FFI call error: %s.", e.func()); return false; } - bool cv25519 = !strcmp(curve, "Curve25519"); - rnp_buffer_destroy(curve); - return cv25519; } bool -cli_rnp_t::get_protection(rnp_key_handle_t handle, - std::string & hash, - std::string & cipher, - size_t & iterations) +cli_rnp_t::get_protection(rnpffi::Key &key, + std::string &hash, + std::string &cipher, + size_t & iterations) { - bool prot = false; - if (rnp_key_is_protected(handle, &prot)) { - ERR_MSG("Error: failed to check key's protection."); - return false; - } - if (!prot) { - hash = ""; - cipher = ""; - iterations = 0; - return true; - } - - char *val = NULL; try { - if (rnp_key_get_protection_hash(handle, &val)) { - ERR_MSG("Error: failed to retrieve key's protection hash."); - return false; - } - hash = val; - rnp_buffer_destroy(val); - if (rnp_key_get_protection_cipher(handle, &val)) { - ERR_MSG("Error: failed to retrieve key's protection cipher."); - return false; - } - cipher = val; - rnp_buffer_destroy(val); - if (rnp_key_get_protection_iterations(handle, &iterations)) { - ERR_MSG("Error: failed to retrieve key's protection iterations."); - return false; + if (!key.is_protected()) { + hash = ""; + cipher = ""; + iterations = 0; + return true; } + hash = key.protection_hash(); + cipher = key.protection_cipher(); + iterations = key.protection_iterations(); return true; - } catch (const std::exception &e) { - ERR_MSG("Error: failed to retrieve key's properties: %s", e.what()); - rnp_buffer_destroy(val); + } catch (const rnpffi::ffi_exception &e) { + ERR_MSG("FFI call error: %s", e.func()); return false; } } @@ -907,96 +872,87 @@ cli_rnp_t::check_cv25519_bits(rnp_key_handle_t key, char *prot_password, bool &t } bool -cli_rnp_t::fix_cv25519_subkey(const std::string &key, bool checkonly) +cli_rnp_t::fix_cv25519_subkey(const std::string &str, bool checkonly) { - std::vector keys; - if (!keys_matching(keys, key, CLI_SEARCH_SECRET | CLI_SEARCH_SUBKEYS)) { - ERR_MSG("Secret keys matching '%s' not found.", key.c_str()); + size_t keys = 0; + auto key = key_matching(str, CLI_SEARCH_SECRET | CLI_SEARCH_SUBKEYS, &keys); + if (!keys) { + ERR_MSG("Secret keys matching '%s' not found.", str.c_str()); return false; } - bool res = false; - std::string prot_hash; - std::string prot_cipher; - size_t prot_iterations; - char * prot_password = NULL; - bool tweaked = false; - - if (keys.size() > 1) { + if (keys > 1) { ERR_MSG( "Ambiguous input: too many keys found for '%s'. Did you use keyid or fingerprint?", - key.c_str()); - goto done; + str.c_str()); + return false; } - cli_rnp_print_key_info(userio_out, ffi, keys[0], true, false); - if (!is_cv25519_subkey(keys[0])) { + cli_rnp_print_key_info(userio_out, ffi, key->handle(), true, false); + if (!is_cv25519_subkey(*key)) { ERR_MSG("Error: specified key is not Curve25519 ECDH subkey."); - goto done; + return false; } - if (!get_protection(keys[0], prot_hash, prot_cipher, prot_iterations)) { - goto done; + std::string prot_hash; + std::string prot_cipher; + size_t prot_iterations; + if (!get_protection(*key, prot_hash, prot_cipher, prot_iterations)) { + return false; } + rnpffi::String prot_password(true); if (!prot_hash.empty() && - (rnp_request_password(ffi, keys[0], "unprotect", &prot_password) || !prot_password)) { + (rnp_request_password(ffi, key->handle(), "unprotect", prot_password.set()) || + !prot_password.c_str())) { ERR_MSG("Error: failed to obtain protection password."); - goto done; + return false; } - if (!check_cv25519_bits(keys[0], prot_password, tweaked)) { - goto done; + bool tweaked = false; + if (!check_cv25519_bits(key->handle(), prot_password.c_str(), tweaked)) { + return false; } if (checkonly) { fprintf(userio_out, tweaked ? "Cv25519 key bits are set correctly and do not require fixing.\n" : "Warning: Cv25519 key bits need fixing.\n"); - res = tweaked; - goto done; + return tweaked; } if (tweaked) { ERR_MSG("Warning: key's bits are fixed already, no action is required."); - res = true; - goto done; + return true; } /* now unprotect so we can tweak bits */ if (!prot_hash.empty()) { - if (rnp_key_unprotect(keys[0], prot_password)) { + if (rnp_key_unprotect(key->handle(), prot_password.c_str())) { ERR_MSG("Error: failed to unprotect key. Did you specify valid password?"); - goto done; + return false; } - if (rnp_key_unlock(keys[0], NULL)) { + if (rnp_key_unlock(key->handle(), NULL)) { ERR_MSG("Error: failed to unlock key."); - goto done; + return false; } } /* tweak key bits and protect back */ - if (rnp_key_25519_bits_tweak(keys[0])) { + if (rnp_key_25519_bits_tweak(key->handle())) { ERR_MSG("Error: failed to tweak key's bits."); - goto done; + return false; } - if (!prot_hash.empty() && rnp_key_protect(keys[0], - prot_password, + if (!prot_hash.empty() && rnp_key_protect(key->handle(), + prot_password.c_str(), prot_cipher.c_str(), NULL, prot_hash.c_str(), prot_iterations)) { ERR_MSG("Error: failed to protect key back."); - goto done; + return false; } - res = cli_rnp_save_keyrings(this); -done: - clear_key_handles(keys); - if (prot_password) { - rnp_buffer_clear(prot_password, strlen(prot_password) + 1); - rnp_buffer_destroy(prot_password); - } - return res; + return cli_rnp_save_keyrings(this); } bool diff --git a/src/rnp/fficli.h b/src/rnp/fficli.h index c3fb1b6c6e..6d7cf096f9 100644 --- a/src/rnp/fficli.h +++ b/src/rnp/fficli.h @@ -47,11 +47,11 @@ class cli_rnp_t { char **subst_argv{}; #endif bool load_keyring(bool secret); - bool is_cv25519_subkey(rnp_key_handle_t handle); - bool get_protection(rnp_key_handle_t handle, - std::string & hash, - std::string & cipher, - size_t & iterations); + bool is_cv25519_subkey(rnpffi::Key &key); + bool get_protection(rnpffi::Key &key, + std::string &hash, + std::string &cipher, + size_t & iterations); bool check_cv25519_bits(rnp_key_handle_t key, char *prot_password, bool &tweaked); public: