wallet: wipe seed from memory where appropriate
This commit is contained in:
@@ -733,10 +733,10 @@ bool WalletImpl::close(bool store)
|
||||
|
||||
std::string WalletImpl::seed() const
|
||||
{
|
||||
std::string seed;
|
||||
epee::wipeable_string seed;
|
||||
if (m_wallet)
|
||||
m_wallet->get_seed(seed);
|
||||
return seed;
|
||||
return std::string(seed.data(), seed.size()); // TODO
|
||||
}
|
||||
|
||||
std::string WalletImpl::getSeedLanguage() const
|
||||
|
||||
+31
-13
@@ -789,7 +789,7 @@ bool wallet2::is_deterministic() const
|
||||
return keys_deterministic;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::get_seed(std::string& electrum_words, const epee::wipeable_string &passphrase) const
|
||||
bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeable_string &passphrase) const
|
||||
{
|
||||
bool keys_deterministic = is_deterministic();
|
||||
if (!keys_deterministic)
|
||||
@@ -815,7 +815,7 @@ bool wallet2::get_seed(std::string& electrum_words, const epee::wipeable_string
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::get_multisig_seed(std::string& seed, const epee::wipeable_string &passphrase, bool raw) const
|
||||
bool wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase, bool raw) const
|
||||
{
|
||||
bool ready;
|
||||
uint32_t threshold, total;
|
||||
@@ -838,7 +838,7 @@ bool wallet2::get_multisig_seed(std::string& seed, const epee::wipeable_string &
|
||||
crypto::secret_key skey;
|
||||
crypto::public_key pkey;
|
||||
const account_keys &keys = get_account().get_keys();
|
||||
std::string data;
|
||||
epee::wipeable_string data;
|
||||
data.append((const char*)&threshold, sizeof(uint32_t));
|
||||
data.append((const char*)&total, sizeof(uint32_t));
|
||||
skey = keys.m_spend_secret_key;
|
||||
@@ -864,7 +864,7 @@ bool wallet2::get_multisig_seed(std::string& seed, const epee::wipeable_string &
|
||||
|
||||
if (raw)
|
||||
{
|
||||
seed = epee::string_tools::buff_to_hex_nodelimer(data);
|
||||
seed = epee::to_hex::wipeable_string({(const unsigned char*)data.data(), data.size()});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3161,7 +3161,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
|
||||
* \param create_address_file Whether to create an address file
|
||||
*/
|
||||
void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password,
|
||||
const std::string& multisig_data, bool create_address_file)
|
||||
const epee::wipeable_string& multisig_data, bool create_address_file)
|
||||
{
|
||||
clear();
|
||||
prepare_file_names(wallet_);
|
||||
@@ -10671,14 +10671,14 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
|
||||
return n_outputs;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::encrypt(const std::string &plaintext, const crypto::secret_key &skey, bool authenticated) const
|
||||
std::string wallet2::encrypt(const char *plaintext, size_t len, const crypto::secret_key &skey, bool authenticated) const
|
||||
{
|
||||
crypto::chacha_key key;
|
||||
crypto::generate_chacha_key(&skey, sizeof(skey), key, m_kdf_rounds);
|
||||
std::string ciphertext;
|
||||
crypto::chacha_iv iv = crypto::rand<crypto::chacha_iv>();
|
||||
ciphertext.resize(plaintext.size() + sizeof(iv) + (authenticated ? sizeof(crypto::signature) : 0));
|
||||
crypto::chacha20(plaintext.data(), plaintext.size(), key, iv, &ciphertext[sizeof(iv)]);
|
||||
ciphertext.resize(len + sizeof(iv) + (authenticated ? sizeof(crypto::signature) : 0));
|
||||
crypto::chacha20(plaintext, len, key, iv, &ciphertext[sizeof(iv)]);
|
||||
memcpy(&ciphertext[0], &iv, sizeof(iv));
|
||||
if (authenticated)
|
||||
{
|
||||
@@ -10692,12 +10692,28 @@ std::string wallet2::encrypt(const std::string &plaintext, const crypto::secret_
|
||||
return ciphertext;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::encrypt(const epee::span<char> &plaintext, const crypto::secret_key &skey, bool authenticated) const
|
||||
{
|
||||
return encrypt(plaintext.data(), plaintext.size(), skey, authenticated);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::encrypt(const std::string &plaintext, const crypto::secret_key &skey, bool authenticated) const
|
||||
{
|
||||
return encrypt(plaintext.data(), plaintext.size(), skey, authenticated);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::encrypt(const epee::wipeable_string &plaintext, const crypto::secret_key &skey, bool authenticated) const
|
||||
{
|
||||
return encrypt(plaintext.data(), plaintext.size(), skey, authenticated);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::encrypt_with_view_secret_key(const std::string &plaintext, bool authenticated) const
|
||||
{
|
||||
return encrypt(plaintext, get_account().get_keys().m_view_secret_key, authenticated);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::decrypt(const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated) const
|
||||
template<typename T>
|
||||
T wallet2::decrypt(const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated) const
|
||||
{
|
||||
const size_t prefix_size = sizeof(chacha_iv) + (authenticated ? sizeof(crypto::signature) : 0);
|
||||
THROW_WALLET_EXCEPTION_IF(ciphertext.size() < prefix_size,
|
||||
@@ -10706,8 +10722,6 @@ std::string wallet2::decrypt(const std::string &ciphertext, const crypto::secret
|
||||
crypto::chacha_key key;
|
||||
crypto::generate_chacha_key(&skey, sizeof(skey), key, m_kdf_rounds);
|
||||
const crypto::chacha_iv &iv = *(const crypto::chacha_iv*)&ciphertext[0];
|
||||
std::string plaintext;
|
||||
plaintext.resize(ciphertext.size() - prefix_size);
|
||||
if (authenticated)
|
||||
{
|
||||
crypto::hash hash;
|
||||
@@ -10718,10 +10732,14 @@ std::string wallet2::decrypt(const std::string &ciphertext, const crypto::secret
|
||||
THROW_WALLET_EXCEPTION_IF(!crypto::check_signature(hash, pkey, signature),
|
||||
error::wallet_internal_error, "Failed to authenticate ciphertext");
|
||||
}
|
||||
crypto::chacha20(ciphertext.data() + sizeof(iv), ciphertext.size() - prefix_size, key, iv, &plaintext[0]);
|
||||
return plaintext;
|
||||
std::unique_ptr<char[]> buffer{new char[ciphertext.size() - prefix_size]};
|
||||
auto wiper = epee::misc_utils::create_scope_leave_handler([&]() { memwipe(buffer.get(), ciphertext.size() - prefix_size); });
|
||||
crypto::chacha20(ciphertext.data() + sizeof(iv), ciphertext.size() - prefix_size, key, iv, buffer.get());
|
||||
return T(buffer.get(), ciphertext.size() - prefix_size);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
template epee::wipeable_string wallet2::decrypt(const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated) const;
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::decrypt_with_view_secret_key(const std::string &ciphertext, bool authenticated) const
|
||||
{
|
||||
return decrypt(ciphertext, get_account().get_keys().m_view_secret_key, authenticated);
|
||||
|
||||
@@ -495,7 +495,7 @@ namespace tools
|
||||
* \param create_address_file Whether to create an address file
|
||||
*/
|
||||
void generate(const std::string& wallet_, const epee::wipeable_string& password,
|
||||
const std::string& multisig_data, bool create_address_file = false);
|
||||
const epee::wipeable_string& multisig_data, bool create_address_file = false);
|
||||
|
||||
/*!
|
||||
* \brief Generates a wallet or restores one.
|
||||
@@ -637,7 +637,7 @@ namespace tools
|
||||
* \brief Checks if deterministic wallet
|
||||
*/
|
||||
bool is_deterministic() const;
|
||||
bool get_seed(std::string& electrum_words, const epee::wipeable_string &passphrase = epee::wipeable_string()) const;
|
||||
bool get_seed(epee::wipeable_string& electrum_words, const epee::wipeable_string &passphrase = epee::wipeable_string()) const;
|
||||
|
||||
/*!
|
||||
* \brief Checks if light wallet. A light wallet sends view key to a server where the blockchain is scanned.
|
||||
@@ -691,7 +691,7 @@ namespace tools
|
||||
bool multisig(bool *ready = NULL, uint32_t *threshold = NULL, uint32_t *total = NULL) const;
|
||||
bool has_multisig_partial_key_images() const;
|
||||
bool has_unknown_key_images() const;
|
||||
bool get_multisig_seed(std::string& seed, const epee::wipeable_string &passphrase = std::string(), bool raw = true) const;
|
||||
bool get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase = std::string(), bool raw = true) const;
|
||||
bool key_on_device() const { return m_key_on_device; }
|
||||
|
||||
// locked & unlocked balance of given or current subaddress account
|
||||
@@ -1054,9 +1054,12 @@ namespace tools
|
||||
void update_pool_state(bool refreshed = false);
|
||||
void remove_obsolete_pool_txs(const std::vector<crypto::hash> &tx_hashes);
|
||||
|
||||
std::string encrypt(const char *plaintext, size_t len, const crypto::secret_key &skey, bool authenticated = true) const;
|
||||
std::string encrypt(const epee::span<char> &span, const crypto::secret_key &skey, bool authenticated = true) const;
|
||||
std::string encrypt(const std::string &plaintext, const crypto::secret_key &skey, bool authenticated = true) const;
|
||||
std::string encrypt(const epee::wipeable_string &plaintext, const crypto::secret_key &skey, bool authenticated = true) const;
|
||||
std::string encrypt_with_view_secret_key(const std::string &plaintext, bool authenticated = true) const;
|
||||
std::string decrypt(const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated = true) const;
|
||||
template<typename T=std::string> T decrypt(const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated = true) const;
|
||||
std::string decrypt_with_view_secret_key(const std::string &ciphertext, bool authenticated = true) const;
|
||||
|
||||
std::string make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const;
|
||||
|
||||
@@ -1574,11 +1574,13 @@ namespace tools
|
||||
|
||||
if (req.key_type.compare("mnemonic") == 0)
|
||||
{
|
||||
if (!m_wallet->get_seed(res.key))
|
||||
epee::wipeable_string seed;
|
||||
if (!m_wallet->get_seed(seed))
|
||||
{
|
||||
er.message = "The wallet is non-deterministic. Cannot display seed.";
|
||||
return false;
|
||||
}
|
||||
res.key = std::string(seed.data(), seed.size()); // send to the network, then wipe RAM :D
|
||||
}
|
||||
else if(req.key_type.compare("view_key") == 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user