trezor: try empty passphrase first
- Try empty passphrase first when opening a wallet, as all Trezors will have passphrase enabled by default by Trezor Suite by default. This feature enables easier access to all users using disabled passphrase (or empty passhprase) - If wallet address differs from device address with empty passphrase, another opening attempt is made, without passphrase suppression, so user can enter his passhprase if using some. In this scenario, nothing changes to user, wallet opening just consumes one more call to Trezor (get wallet address with empty passphrase) - also change how m_passphrase is used. Previous version did not work well with recent passphrase entry mechanism change (made in Trezor), thus this commit fixes the behaviour).
This commit is contained in:
parent
ed506006d2
commit
13a8a576ed
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
/* ======================================================================= */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue