aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/device/device_cold.hpp20
-rw-r--r--src/device_trezor/device_trezor.cpp21
-rw-r--r--src/device_trezor/device_trezor.hpp20
-rw-r--r--src/device_trezor/device_trezor_base.cpp29
-rw-r--r--src/device_trezor/device_trezor_base.hpp3
-rw-r--r--src/wallet/wallet2.cpp21
6 files changed, 103 insertions, 11 deletions
diff --git a/src/device/device_cold.hpp b/src/device/device_cold.hpp
index d435b448c..07009b9d2 100644
--- a/src/device/device_cold.hpp
+++ b/src/device/device_cold.hpp
@@ -162,6 +162,26 @@ namespace hw {
* Live refresh process termination
*/
virtual void live_refresh_finish() =0;
+
+ /**
+ * Requests public address, uses empty passphrase if asked for.
+ */
+ virtual bool get_public_address_with_no_passphrase(cryptonote::account_public_address &pubkey) =0;
+
+ /**
+ * Reset session ID, restart with a new session.
+ */
+ virtual void reset_session() =0;
+
+ /**
+ * Returns true if device already asked for passphrase entry before (i.e., obviously supports passphrase entry)
+ */
+ virtual bool seen_passphrase_entry_prompt() =0;
+
+ /**
+ * Uses empty passphrase for all passphrase queries.
+ */
+ virtual void set_use_empty_passphrase(bool always_use_empty_passphrase) =0;
};
}
diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp
index c2070b0d1..03e8bbba4 100644
--- a/src/device_trezor/device_trezor.cpp
+++ b/src/device_trezor/device_trezor.cpp
@@ -178,6 +178,15 @@ namespace trezor {
}
}
+ bool device_trezor::get_public_address_with_no_passphrase(cryptonote::account_public_address &pubkey) {
+ m_reply_with_empty_passphrase = true;
+ const auto empty_passphrase_reverter = epee::misc_utils::create_scope_leave_handler([&]() {
+ m_reply_with_empty_passphrase = false;
+ });
+
+ return get_public_address(pubkey);
+ }
+
bool device_trezor::get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) {
try {
MDEBUG("Loading view-only key from the Trezor. Please check the Trezor for a confirmation.");
@@ -206,6 +215,18 @@ namespace trezor {
get_address(index, payment_id, true);
}
+ void device_trezor::reset_session() {
+ m_device_session_id.clear();
+ }
+
+ bool device_trezor::seen_passphrase_entry_prompt() {
+ return m_seen_passphrase_entry_message;
+ }
+
+ void device_trezor::set_use_empty_passphrase(bool always_use_empty_passphrase) {
+ m_always_use_empty_passphrase = always_use_empty_passphrase;
+ }
+
/* ======================================================================= */
/* Helpers */
/* ======================================================================= */
diff --git a/src/device_trezor/device_trezor.hpp b/src/device_trezor/device_trezor.hpp
index d91d1de3f..15337d2b4 100644
--- a/src/device_trezor/device_trezor.hpp
+++ b/src/device_trezor/device_trezor.hpp
@@ -205,6 +205,26 @@ namespace trezor {
const ::tools::wallet2::unsigned_tx_set & unsigned_tx,
::tools::wallet2::signed_tx_set & signed_tx,
hw::tx_aux_data & aux_data) override;
+
+ /**
+ * Requests public address, uses empty passphrase if asked for.
+ */
+ bool get_public_address_with_no_passphrase(cryptonote::account_public_address &pubkey) override;
+
+ /**
+ * Reset session ID, restart with a new session.
+ */
+ virtual void reset_session() override;
+
+ /**
+ * Returns true if device already asked for passphrase entry before (i.e., obviously supports passphrase entry)
+ */
+ bool seen_passphrase_entry_prompt() override;
+
+ /**
+ * Uses empty passphrase for all passphrase queries.
+ */
+ void set_use_empty_passphrase(bool use_always_empty_passphrase) override;
};
#endif
diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp
index b0b4342f5..016eb2816 100644
--- a/src/device_trezor/device_trezor_base.cpp
+++ b/src/device_trezor/device_trezor_base.cpp
@@ -45,7 +45,10 @@ namespace trezor {
const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080};
- device_trezor_base::device_trezor_base(): m_callback(nullptr), m_last_msg_type(messages::MessageType_Success) {
+ device_trezor_base::device_trezor_base(): m_callback(nullptr), m_last_msg_type(messages::MessageType_Success),
+ m_reply_with_empty_passphrase(false),
+ m_always_use_empty_passphrase(false),
+ m_seen_passphrase_entry_message(false) {
#ifdef WITH_TREZOR_DEBUGGING
m_debug = false;
#endif
@@ -155,6 +158,9 @@ namespace trezor {
TREZOR_AUTO_LOCK_DEVICE();
m_device_session_id.clear();
m_features.reset();
+ m_seen_passphrase_entry_message = false;
+ m_reply_with_empty_passphrase = false;
+ m_always_use_empty_passphrase = false;
if (m_transport){
try {
@@ -476,6 +482,7 @@ namespace trezor {
return;
}
+ m_seen_passphrase_entry_message = true;
bool on_device = true;
if (msg->has__on_device() && !msg->_on_device()){
on_device = false; // do not enter on device, old devices.
@@ -491,19 +498,21 @@ namespace trezor {
}
boost::optional<epee::wipeable_string> passphrase;
- TREZOR_CALLBACK_GET(passphrase, on_passphrase_request, on_device);
+ if (m_reply_with_empty_passphrase || m_always_use_empty_passphrase) {
+ MDEBUG("Answering passphrase prompt with an empty passphrase, always use empty: " << m_always_use_empty_passphrase);
+ on_device = false;
+ passphrase = epee::wipeable_string("");
+ } else if (m_passphrase){
+ MWARNING("Answering passphrase prompt with a stored passphrase (do not use; passphrase can be seen by a potential malware / attacker)");
+ on_device = false;
+ passphrase = epee::wipeable_string(m_passphrase.get());
+ } else {
+ TREZOR_CALLBACK_GET(passphrase, on_passphrase_request, on_device);
+ }
messages::common::PassphraseAck m;
m.set_on_device(on_device);
if (!on_device) {
- if (!passphrase && m_passphrase) {
- passphrase = m_passphrase;
- }
-
- if (m_passphrase) {
- m_passphrase = boost::none;
- }
-
if (passphrase) {
m.set_allocated_passphrase(new std::string(passphrase->data(), passphrase->size()));
}
diff --git a/src/device_trezor/device_trezor_base.hpp b/src/device_trezor/device_trezor_base.hpp
index 0162b23df..de49397d5 100644
--- a/src/device_trezor/device_trezor_base.hpp
+++ b/src/device_trezor/device_trezor_base.hpp
@@ -101,6 +101,9 @@ namespace trezor {
messages::MessageType m_last_msg_type;
cryptonote::network_type network_type;
+ bool m_reply_with_empty_passphrase;
+ bool m_always_use_empty_passphrase;
+ bool m_seen_passphrase_entry_message;
#ifdef WITH_TREZOR_DEBUGGING
std::shared_ptr<trezor_debug_callback> m_debug_callback;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 721a7faf8..744a63e7d 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -4424,7 +4424,26 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
m_account.set_device(hwdev);
account_public_address device_account_public_address;
- THROW_WALLET_EXCEPTION_IF(!hwdev.get_public_address(device_account_public_address), error::wallet_internal_error, "Cannot get a device address");
+ bool fetch_device_address = true;
+
+ ::hw::device_cold* dev_cold = nullptr;
+ if (m_key_device_type == hw::device::device_type::TREZOR && (dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev)) != nullptr) {
+ THROW_WALLET_EXCEPTION_IF(!dev_cold->get_public_address_with_no_passphrase(device_account_public_address), error::wallet_internal_error, "Cannot get a device address");
+ if (device_account_public_address == m_account.get_keys().m_account_address) {
+ LOG_PRINT_L0("Wallet opened with an empty passphrase");
+ fetch_device_address = false;
+ dev_cold->set_use_empty_passphrase(true);
+ } else {
+ fetch_device_address = true;
+ LOG_PRINT_L0("Wallet opening with an empty passphrase failed. Retry again: " << fetch_device_address);
+ dev_cold->reset_session();
+ }
+ }
+
+ if (fetch_device_address) {
+ THROW_WALLET_EXCEPTION_IF(!hwdev.get_public_address(device_account_public_address), error::wallet_internal_error, "Cannot get a device address");
+ }
+
THROW_WALLET_EXCEPTION_IF(device_account_public_address != m_account.get_keys().m_account_address, error::wallet_internal_error, "Device wallet does not match wallet address. If the device uses the passphrase feature, please check whether the passphrase was entered correctly (it may have been misspelled - different passphrases generate different wallets, passphrase is case-sensitive). "
"Device address: " + cryptonote::get_account_address_as_str(m_nettype, false, device_account_public_address) +
", wallet address: " + m_account.get_public_address_str(m_nettype));