mirror of
https://github.com/monero-project/monero.git
synced 2026-06-12 19:11:36 -07:00
Merge pull request #9860
dbc8402 wallet: fix wallet_keys_unlocker (jeffro256)
This commit is contained in:
+36
-52
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <queue>
|
||||
@@ -1098,50 +1099,46 @@ uint64_t gamma_picker::pick()
|
||||
};
|
||||
|
||||
boost::mutex wallet_keys_unlocker::lockers_lock;
|
||||
unsigned int wallet_keys_unlocker::lockers = 0;
|
||||
wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, const boost::optional<tools::password_container> &password):
|
||||
std::map<wallet2*, std::size_t> wallet_keys_unlocker::lockers_per_wallet = {};
|
||||
wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, const epee::wipeable_string *password):
|
||||
w(w),
|
||||
locked(password != boost::none)
|
||||
should_relock(true)
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lock(lockers_lock);
|
||||
if (lockers++ > 0)
|
||||
locked = false;
|
||||
if (!locked || w.is_unattended() || w.ask_password() != tools::wallet2::AskPasswordToDecrypt || w.watch_only() || w.is_background_syncing())
|
||||
static_assert(!std::is_move_assignable_v<wallet2> && !std::is_move_constructible_v<wallet2>,
|
||||
"Keeping track of wallet instances by pointer doesn't work if wallet2 can be moved");
|
||||
|
||||
if (password == nullptr || !w.is_key_encryption_enabled())
|
||||
{
|
||||
locked = false;
|
||||
should_relock = false;
|
||||
return;
|
||||
}
|
||||
const epee::wipeable_string pass = password->password();
|
||||
w.generate_chacha_key_from_password(pass, key);
|
||||
w.decrypt_keys(key);
|
||||
}
|
||||
|
||||
wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, bool locked, const epee::wipeable_string &password):
|
||||
w(w),
|
||||
locked(locked)
|
||||
{
|
||||
w.generate_chacha_key_from_password(*password, key);
|
||||
|
||||
boost::lock_guard<boost::mutex> lock(lockers_lock);
|
||||
if (lockers++ > 0)
|
||||
locked = false;
|
||||
if (!locked)
|
||||
if (lockers_per_wallet[std::addressof(w)]++ > 0)
|
||||
return;
|
||||
w.generate_chacha_key_from_password(password, key);
|
||||
|
||||
w.decrypt_keys(key);
|
||||
}
|
||||
|
||||
wallet_keys_unlocker::~wallet_keys_unlocker()
|
||||
{
|
||||
if (!should_relock)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lock(lockers_lock);
|
||||
if (lockers == 0)
|
||||
wallet2* w_ptr = std::addressof(w);
|
||||
if (lockers_per_wallet[w_ptr] == 0)
|
||||
{
|
||||
MERROR("There are no lockers in wallet_keys_unlocker dtor");
|
||||
return;
|
||||
}
|
||||
--lockers;
|
||||
if (!locked)
|
||||
return;
|
||||
if (--lockers_per_wallet[w_ptr] > 0)
|
||||
return; // there are other unlock-ers for this wallet, do nothing for now
|
||||
lockers_per_wallet.erase(w_ptr);
|
||||
w.encrypt_keys(key);
|
||||
}
|
||||
catch (...)
|
||||
@@ -2206,7 +2203,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
|
||||
boost::optional<epee::wipeable_string> pwd = m_callback->on_get_password(pool ? "output found in pool" : "output received");
|
||||
THROW_WALLET_EXCEPTION_IF(!pwd, error::password_needed, tr("Password is needed to compute key image for incoming monero"));
|
||||
THROW_WALLET_EXCEPTION_IF(!verify_password(*pwd), error::password_needed, tr("Invalid password: password is needed to compute key image for incoming monero"));
|
||||
m_encrypt_keys_after_refresh.reset(new wallet_keys_unlocker(*this, m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only, *pwd));
|
||||
m_encrypt_keys_after_refresh.reset(new wallet_keys_unlocker(*this, &*pwd));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5438,6 +5435,14 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
|
||||
return r;
|
||||
}
|
||||
|
||||
bool wallet2::is_key_encryption_enabled() const
|
||||
{
|
||||
return !is_unattended()
|
||||
&& ask_password() == tools::wallet2::AskPasswordToDecrypt
|
||||
&& !watch_only()
|
||||
&& !is_background_syncing();
|
||||
}
|
||||
|
||||
void wallet2::encrypt_keys(const crypto::chacha_key &key)
|
||||
{
|
||||
m_account.encrypt_keys(key);
|
||||
@@ -5838,27 +5843,6 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
epee::misc_utils::auto_scope_leave_caller wallet2::decrypt_account_for_multisig(const epee::wipeable_string &password)
|
||||
{
|
||||
// decrypt account keys
|
||||
// note: this conditional's clauses are old and undocumented
|
||||
epee::misc_utils::auto_scope_leave_caller keys_reencryptor;
|
||||
if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only)
|
||||
{
|
||||
crypto::chacha_key chacha_key;
|
||||
crypto::generate_chacha_key(password.data(), password.size(), chacha_key, m_kdf_rounds);
|
||||
this->decrypt_keys(chacha_key);
|
||||
keys_reencryptor = epee::misc_utils::create_scope_leave_handler(
|
||||
[this, chacha_key]()
|
||||
{
|
||||
this->encrypt_keys(chacha_key);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return keys_reencryptor;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::get_uninitialized_multisig_account(multisig::multisig_account &account_out) const
|
||||
{
|
||||
// create uninitialized multisig account
|
||||
@@ -5904,7 +5888,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
|
||||
const std::uint32_t threshold)
|
||||
{
|
||||
// decrypt account keys
|
||||
epee::misc_utils::auto_scope_leave_caller keys_reencryptor{this->decrypt_account_for_multisig(password)};
|
||||
std::optional<wallet_keys_unlocker> unlocker(std::in_place, *this, &password);
|
||||
|
||||
// create multisig account
|
||||
multisig::multisig_account multisig_account;
|
||||
@@ -5982,7 +5966,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
|
||||
m_account_public_address.m_spend_public_key = multisig_account.get_multisig_pubkey();
|
||||
|
||||
// re-encrypt keys
|
||||
keys_reencryptor = epee::misc_utils::auto_scope_leave_caller();
|
||||
unlocker.reset();
|
||||
|
||||
if (!m_wallet_file.empty())
|
||||
this->create_keys_file(m_wallet_file, false, password, boost::filesystem::exists(m_wallet_file + ".address.txt"));
|
||||
@@ -6003,7 +5987,7 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor
|
||||
CHECK_AND_ASSERT_THROW_MES(ms_status.multisig_is_active, "The wallet is not multisig");
|
||||
|
||||
// decrypt account keys
|
||||
epee::misc_utils::auto_scope_leave_caller keys_reencryptor{this->decrypt_account_for_multisig(password)};
|
||||
std::optional<wallet_keys_unlocker> unlocker(std::in_place, *this, &password);
|
||||
|
||||
// reconstruct multisig account
|
||||
multisig::multisig_account multisig_account;
|
||||
@@ -6055,7 +6039,7 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor
|
||||
if (multisig_account.multisig_is_ready())
|
||||
{
|
||||
// keys are encrypted again
|
||||
keys_reencryptor = epee::misc_utils::auto_scope_leave_caller();
|
||||
unlocker.reset();
|
||||
|
||||
if (!m_wallet_file.empty())
|
||||
{
|
||||
@@ -6101,7 +6085,7 @@ std::string wallet2::get_multisig_key_exchange_booster(const epee::wipeable_stri
|
||||
CHECK_AND_ASSERT_THROW_MES(kex_messages.size() > 0, "No key exchange messages passed in.");
|
||||
|
||||
// decrypt account keys
|
||||
epee::misc_utils::auto_scope_leave_caller keys_reencryptor{this->decrypt_account_for_multisig(password)};
|
||||
wallet_keys_unlocker unlocker(*this, &password);
|
||||
|
||||
// prepare multisig account
|
||||
multisig::multisig_account multisig_account;
|
||||
@@ -6489,7 +6473,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
|
||||
THROW_WALLET_EXCEPTION_IF(true, error::file_read_error, "failed to load keys from buffer");
|
||||
}
|
||||
|
||||
wallet_keys_unlocker unlocker(*this, m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only && !m_is_background_wallet, password);
|
||||
wallet_keys_unlocker unlocker(*this, &password);
|
||||
|
||||
//keys loaded ok!
|
||||
//try to load wallet cache. but even if we failed, it is not big problem
|
||||
|
||||
Reference in New Issue
Block a user