wallet2: guard against race with multiple decrypt_keys users

If more than one thread wants to make sure of the spend secret key,
then we decrypt on the first caller and reencrypt on the last caller,
otherwise we could use an invalid secret key.
This commit is contained in:
moneromooo-monero 2019-12-14 21:15:02 +00:00
parent b4e1dc83d2
commit f717d5936c
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
2 changed files with 9 additions and 0 deletions

View file

@ -1186,6 +1186,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
m_ringdb(), m_ringdb(),
m_last_block_reward(0), m_last_block_reward(0),
m_encrypt_keys_after_refresh(boost::none), m_encrypt_keys_after_refresh(boost::none),
m_decrypt_keys_lockers(0),
m_unattended(unattended), m_unattended(unattended),
m_devices_registered(false), m_devices_registered(false),
m_device_last_key_image_sync(0), m_device_last_key_image_sync(0),
@ -4343,12 +4344,18 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
void wallet2::encrypt_keys(const crypto::chacha_key &key) void wallet2::encrypt_keys(const crypto::chacha_key &key)
{ {
boost::lock_guard<boost::mutex> lock(m_decrypt_keys_lock);
if (--m_decrypt_keys_lockers) // another lock left ?
return;
m_account.encrypt_keys(key); m_account.encrypt_keys(key);
m_account.decrypt_viewkey(key); m_account.decrypt_viewkey(key);
} }
void wallet2::decrypt_keys(const crypto::chacha_key &key) void wallet2::decrypt_keys(const crypto::chacha_key &key)
{ {
boost::lock_guard<boost::mutex> lock(m_decrypt_keys_lock);
if (m_decrypt_keys_lockers++) // already unlocked ?
return;
m_account.encrypt_viewkey(key); m_account.encrypt_viewkey(key);
m_account.decrypt_keys(key); m_account.decrypt_keys(key);
} }

View file

@ -1613,6 +1613,8 @@ private:
crypto::chacha_key m_cache_key; crypto::chacha_key m_cache_key;
boost::optional<epee::wipeable_string> m_encrypt_keys_after_refresh; boost::optional<epee::wipeable_string> m_encrypt_keys_after_refresh;
boost::mutex m_decrypt_keys_lock;
unsigned int m_decrypt_keys_lockers;
bool m_unattended; bool m_unattended;
bool m_devices_registered; bool m_devices_registered;