diff options
Diffstat (limited to 'src/device_trezor/device_trezor_base.cpp')
-rw-r--r-- | src/device_trezor/device_trezor_base.cpp | 103 |
1 files changed, 92 insertions, 11 deletions
diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp index 38c20c30b..5071932ee 100644 --- a/src/device_trezor/device_trezor_base.cpp +++ b/src/device_trezor/device_trezor_base.cpp @@ -28,6 +28,9 @@ // #include "device_trezor_base.hpp" +#include <boost/algorithm/string/classification.hpp> +#include <boost/algorithm/string/split.hpp> +#include <boost/regex.hpp> namespace hw { namespace trezor { @@ -36,10 +39,11 @@ namespace trezor { #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "device.trezor" +#define TREZOR_BIP44_HARDENED_ZERO 0x80000000 - const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080, 0x80000000}; + const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080}; - device_trezor_base::device_trezor_base() { + device_trezor_base::device_trezor_base(): m_callback(nullptr) { } @@ -61,7 +65,7 @@ namespace trezor { } bool device_trezor_base::set_name(const std::string & name) { - this->full_name = name; + this->m_full_name = name; this->name = ""; auto delim = name.find(':'); @@ -73,10 +77,10 @@ namespace trezor { } const std::string device_trezor_base::get_name() const { - if (this->full_name.empty()) { + if (this->m_full_name.empty()) { return std::string("<disconnected:").append(this->name).append(">"); } - return this->full_name; + return this->m_full_name; } bool device_trezor_base::init() { @@ -135,6 +139,9 @@ namespace trezor { } bool device_trezor_base::disconnect() { + m_device_state.clear(); + m_features.reset(); + if (m_transport){ try { m_transport->close(); @@ -189,6 +196,25 @@ namespace trezor { } } + void device_trezor_base::require_initialized(){ + if (!m_features){ + throw exc::TrezorException("Device state not initialized"); + } + + if (m_features->has_bootloader_mode() && m_features->bootloader_mode()){ + throw exc::TrezorException("Device is in the bootloader mode"); + } + + if (m_features->has_firmware_present() && !m_features->firmware_present()){ + throw exc::TrezorException("Device has no firmware loaded"); + } + + // Hard requirement on initialized field, has to be there. + if (!m_features->has_initialized() || !m_features->initialized()){ + throw exc::TrezorException("Device is not initialized"); + } + } + void device_trezor_base::call_ping_unsafe(){ auto pingMsg = std::make_shared<messages::management::Ping>(); pingMsg->set_message("PING"); @@ -213,7 +239,7 @@ namespace trezor { void device_trezor_base::write_raw(const google::protobuf::Message * msg){ require_connected(); CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); - this->getTransport()->write(*msg); + this->get_transport()->write(*msg); } GenericMessage device_trezor_base::read_raw(){ @@ -221,7 +247,7 @@ namespace trezor { std::shared_ptr<google::protobuf::Message> msg_resp; hw::trezor::messages::MessageType msg_resp_type; - this->getTransport()->read(msg_resp, &msg_resp_type); + this->get_transport()->read(msg_resp, &msg_resp_type); return GenericMessage(msg_resp_type, msg_resp); } @@ -252,6 +278,39 @@ namespace trezor { } } + void device_trezor_base::ensure_derivation_path() noexcept { + if (m_wallet_deriv_path.empty()){ + m_wallet_deriv_path.push_back(TREZOR_BIP44_HARDENED_ZERO); // default 0' + } + } + + void device_trezor_base::set_derivation_path(const std::string &deriv_path){ + this->m_wallet_deriv_path.clear(); + + if (deriv_path.empty() || deriv_path == "-"){ + ensure_derivation_path(); + return; + } + + CHECK_AND_ASSERT_THROW_MES(deriv_path.size() <= 255, "Derivation path is too long"); + + std::vector<std::string> fields; + boost::split(fields, deriv_path, boost::is_any_of("/")); + CHECK_AND_ASSERT_THROW_MES(fields.size() <= 10, "Derivation path is too long"); + + boost::regex rgx("^([0-9]+)'?$"); + boost::cmatch match; + + this->m_wallet_deriv_path.reserve(fields.size()); + for(const std::string & cur : fields){ + const bool ok = boost::regex_match(cur.c_str(), match, rgx); + CHECK_AND_ASSERT_THROW_MES(ok, "Invalid wallet code: " << deriv_path << ". Invalid path element: " << cur); + CHECK_AND_ASSERT_THROW_MES(match[0].length() > 0, "Invalid wallet code: " << deriv_path << ". Invalid path element: " << cur); + + const unsigned long cidx = std::stoul(match[0].str()) | TREZOR_BIP44_HARDENED_ZERO; + this->m_wallet_deriv_path.push_back((unsigned int)cidx); + } + } /* ======================================================================= */ /* TREZOR PROTOCOL */ @@ -277,6 +336,25 @@ namespace trezor { return false; } + void device_trezor_base::device_state_reset_unsafe() + { + require_connected(); + auto initMsg = std::make_shared<messages::management::Initialize>(); + + if(!m_device_state.empty()) { + initMsg->set_allocated_state(&m_device_state); + } + + m_features = this->client_exchange<messages::management::Features>(initMsg); + initMsg->release_state(); + } + + void device_trezor_base::device_state_reset() + { + AUTO_LOCK_CMD(); + device_state_reset_unsafe(); + } + void device_trezor_base::on_button_request(GenericMessage & resp, const messages::common::ButtonRequest * msg) { CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); @@ -324,7 +402,13 @@ namespace trezor { // TODO: remove passphrase from memory m.set_passphrase(passphrase.data(), passphrase.size()); } + + if (!m_device_state.empty()){ + m.set_allocated_state(&m_device_state); + } + resp = call_raw(&m); + m.release_state(); } void device_trezor_base::on_passphrase_state_request(GenericMessage & resp, const messages::common::PassphraseStateRequest * msg) @@ -332,10 +416,7 @@ namespace trezor { MDEBUG("on_passhprase_state_request"); CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); - if (m_callback){ - m_callback->on_passphrase_state_request(msg->state()); - } - + m_device_state = msg->state(); messages::common::PassphraseStateAck m; resp = call_raw(&m); } |