aboutsummaryrefslogtreecommitdiff
path: root/src/device_trezor/device_trezor_base.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/device_trezor/device_trezor_base.cpp')
-rw-r--r--src/device_trezor/device_trezor_base.cpp103
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);
}