Skip to content
Permalink
Browse files

device/trezor: debugging features, trezor tests

  • Loading branch information...
ph4r05 committed Nov 20, 2018
1 parent 31bdf7b commit 5ea17909caec3ca9f96e3dbd360ee952528de43c
@@ -63,6 +63,10 @@ debug-test:
mkdir -p $(builddir)/debug
cd $(builddir)/debug && cmake -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=Debug $(topdir) && $(MAKE) && $(MAKE) ARGS="-E libwallet_api_tests" test
debug-test-trezor:
mkdir -p $(builddir)/debug
cd $(builddir)/debug && cmake -D BUILD_TESTS=ON -D TREZOR_DEBUG=ON -D CMAKE_BUILD_TYPE=Debug $(topdir) && $(MAKE) && $(MAKE) ARGS="-E libwallet_api_tests" test
debug-all:
mkdir -p $(builddir)/debug
cd $(builddir)/debug && cmake -D BUILD_TESTS=ON -D BUILD_SHARED_LIBS=OFF -D CMAKE_BUILD_TYPE=Debug $(topdir) && $(MAKE)
@@ -1,6 +1,8 @@
OPTION(USE_DEVICE_TREZOR "Trezor support compilation" ON)
OPTION(USE_DEVICE_TREZOR_LIBUSB "Trezor LibUSB compilation" ON)
OPTION(USE_DEVICE_TREZOR_UDP_RELEASE "Trezor UdpTransport in release mode" OFF)
OPTION(USE_DEVICE_TREZOR_DEBUG "Trezor Debugging enabled" OFF)
OPTION(TREZOR_DEBUG "Main trezor debugging switch" OFF)

# Helper function to fix cmake < 3.6.0 FindProtobuf variables
function(_trezor_protobuf_fix_vars)
@@ -53,6 +55,14 @@ if (USE_DEVICE_TREZOR)
set(Protobuf_FOUND 1) # override found if all rquired info was provided by variables
endif()

if(TREZOR_DEBUG)
set(USE_DEVICE_TREZOR_DEBUG 1)
endif()

# Compile debugging support (for tests)
if (USE_DEVICE_TREZOR_DEBUG)
add_definitions(-DWITH_TREZOR_DEBUGGING=1)
endif()
else()
message(STATUS "Trezor support disabled by USE_DEVICE_TREZOR")
endif()
@@ -106,7 +116,12 @@ endif()
if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON AND Protobuf_COMPILE_TEST_PASSED)
set(ENV{PROTOBUF_INCLUDE_DIRS} "${Protobuf_INCLUDE_DIR}")
set(ENV{PROTOBUF_PROTOC_EXECUTABLE} "${Protobuf_PROTOC_EXECUTABLE}")
execute_process(COMMAND ${TREZOR_PYTHON} tools/build_protob.py WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../src/device_trezor/trezor RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR)
set(TREZOR_PROTOBUF_PARAMS "")
if (USE_DEVICE_TREZOR_DEBUG)
set(TREZOR_PROTOBUF_PARAMS "--debug")
endif()

execute_process(COMMAND ${TREZOR_PYTHON} tools/build_protob.py ${TREZOR_PROTOBUF_PARAMS} WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../src/device_trezor/trezor RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR)
if(RET)
message(WARNING "Trezor protobuf messages could not be regenerated (err=${RET}, python ${PYTHON})."
"OUT: ${OUT}, ERR: ${ERR}."
@@ -67,6 +67,12 @@ set(trezor_private_headers)
if(DEVICE_TREZOR_READY)
message(STATUS "Trezor support enabled")

if(USE_DEVICE_TREZOR_DEBUG)
list(APPEND trezor_headers trezor/debug_link.hpp trezor/messages/messages-debug.pb.h)
list(APPEND trezor_sources trezor/debug_link.cpp trezor/messages/messages-debug.pb.cc)
message(STATUS "Trezor debugging enabled")
endif()

monero_private_headers(device_trezor
${device_private_headers})

@@ -97,7 +97,14 @@ namespace trezor {
auto res = get_view_key();
CHECK_AND_ASSERT_MES(res->watch_key().size() == 32, false, "Trezor returned invalid view key");

// Trezor does not make use of spendkey of the device API.
// Ledger loads encrypted spendkey, Trezor loads null key (never leaves device).
// In the test (debugging mode) we need to leave this field intact as it is already set by
// the debugging code and need to remain same for the testing purposes.
#ifndef WITH_TREZOR_DEBUGGING
spendkey = crypto::null_skey; // not given
#endif

memcpy(viewkey.data, res->watch_key().data(), 32);

return true;
@@ -362,13 +369,9 @@ namespace trezor {
CHECK_AND_ASSERT_THROW_MES(m_features, "Device state not initialized"); // make sure the caller did not reset features
const bool nonce_required = init_msg->tsx_data().has_payment_id() && init_msg->tsx_data().payment_id().size() > 0;

if (nonce_required){
if (nonce_required && init_msg->tsx_data().payment_id().size() == 8){
// Versions 2.0.9 and lower do not support payment ID
CHECK_AND_ASSERT_THROW_MES(m_features->has_major_version() && m_features->has_minor_version() && m_features->has_patch_version(), "Invalid Trezor firmware version information");
const uint32_t vma = m_features->major_version();
const uint32_t vmi = m_features->minor_version();
const uint32_t vpa = m_features->patch_version();
if (vma < 2 || (vma == 2 && vmi == 0 && vpa <= 9)) {
if (get_version() <= pack_version(2, 0, 9)) {
throw exc::TrezorException("Trezor firmware 2.0.9 and lower does not support transactions with short payment IDs or integrated addresses. Please update.");
}
}
@@ -44,7 +44,9 @@ namespace trezor {
const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080};

device_trezor_base::device_trezor_base(): m_callback(nullptr) {

#ifdef WITH_TREZOR_DEBUGGING
m_debug = false;
#endif
}

device_trezor_base::~device_trezor_base() {
@@ -130,6 +132,10 @@ namespace trezor {
}

m_transport->open();

#ifdef WITH_TREZOR_DEBUGGING
setup_debug();
#endif
return true;

} catch(std::exception const& e){
@@ -153,6 +159,13 @@ namespace trezor {
return false;
}
}

#ifdef WITH_TREZOR_DEBUGGING
if (m_debug_callback) {
m_debug_callback->on_disconnect();
m_debug_callback = nullptr;
}
#endif
return true;
}

@@ -355,6 +368,32 @@ namespace trezor {
device_state_reset_unsafe();
}

#ifdef WITH_TREZOR_DEBUGGING
#define TREZOR_CALLBACK(method, ...) do { \
if (m_debug_callback) m_debug_callback->method(__VA_ARGS__); \
if (m_callback) m_callback->method(__VA_ARGS__); \
}while(0)

void device_trezor_base::setup_debug(){
if (!m_debug){
return;
}

if (!m_debug_callback){
CHECK_AND_ASSERT_THROW_MES(m_transport, "Transport does not exist");
auto debug_transport = m_transport->find_debug();
if (debug_transport) {
m_debug_callback = std::make_shared<trezor_debug_callback>(debug_transport);
} else {
MDEBUG("Transport does not have debug link option");
}
}
}

#else
#define TREZOR_CALLBACK(method, ...) do { if (m_callback) m_callback->method(__VA_ARGS__); } while(0)
#endif

void device_trezor_base::on_button_request(GenericMessage & resp, const messages::common::ButtonRequest * msg)
{
CHECK_AND_ASSERT_THROW_MES(msg, "Empty message");
@@ -363,10 +402,7 @@ namespace trezor {
messages::common::ButtonAck ack;
write_raw(&ack);

if (m_callback){
m_callback->on_button_request();
}

TREZOR_CALLBACK(on_button_request);
resp = read_raw();
}

@@ -377,9 +413,7 @@ namespace trezor {

epee::wipeable_string pin;

if (m_callback){
m_callback->on_pin_request(pin);
}
TREZOR_CALLBACK(on_pin_request, pin);

// TODO: remove PIN from memory
messages::common::PinMatrixAck m;
@@ -393,9 +427,7 @@ namespace trezor {
MDEBUG("on_passhprase_request, on device: " << msg->on_device());
epee::wipeable_string passphrase;

if (m_callback){
m_callback->on_passphrase_request(msg->on_device(), passphrase);
}
TREZOR_CALLBACK(on_passphrase_request, msg->on_device(), passphrase);

messages::common::PassphraseAck m;
if (!msg->on_device()){
@@ -421,5 +453,67 @@ namespace trezor {
resp = call_raw(&m);
}

#ifdef WITH_TREZOR_DEBUGGING
void device_trezor_base::wipe_device()
{
auto msg = std::make_shared<messages::management::WipeDevice>();
auto ret = client_exchange<messages::common::Success>(msg);
(void)ret;
init_device();
}

void device_trezor_base::init_device()
{
auto msg = std::make_shared<messages::management::Initialize>();
m_features = client_exchange<messages::management::Features>(msg);
}

void device_trezor_base::load_device(const std::string & mnemonic, const std::string & pin,
bool passphrase_protection, const std::string & label, const std::string & language,
bool skip_checksum, bool expand)
{
if (m_features && m_features->initialized()){
throw std::runtime_error("Device is initialized already. Call device.wipe() and try again.");
}

auto msg = std::make_shared<messages::management::LoadDevice>();
msg->set_mnemonic(mnemonic);
msg->set_pin(pin);
msg->set_passphrase_protection(passphrase_protection);
msg->set_label(label);
msg->set_language(language);
msg->set_skip_checksum(skip_checksum);
auto ret = client_exchange<messages::common::Success>(msg);
(void)ret;

init_device();
}

trezor_debug_callback::trezor_debug_callback(std::shared_ptr<Transport> & debug_transport){
m_debug_link = std::make_shared<DebugLink>();
m_debug_link->init(debug_transport);
}

void trezor_debug_callback::on_button_request() {
if (m_debug_link) m_debug_link->press_yes();
}

void trezor_debug_callback::on_pin_request(epee::wipeable_string &pin) {

}

void trezor_debug_callback::on_passphrase_request(bool on_device, epee::wipeable_string &passphrase) {

}

void trezor_debug_callback::on_passphrase_state_request(const std::string &state) {

}

void trezor_debug_callback::on_disconnect(){
if (m_debug_link) m_debug_link->close();
}
#endif

#endif //WITH_DEVICE_TREZOR
}}
@@ -42,6 +42,10 @@
#include "cryptonote_config.h"
#include "trezor.hpp"

#ifdef WITH_TREZOR_DEBUGGING
#include "trezor/debug_link.hpp"
#endif

//automatic lock one more level on device ensuring the current thread is allowed to use it
#define AUTO_LOCK_CMD() \
/* lock both mutexes without deadlock*/ \
@@ -57,6 +61,23 @@ namespace trezor {
#ifdef WITH_DEVICE_TREZOR
class device_trezor_base;

#ifdef WITH_TREZOR_DEBUGGING
class trezor_debug_callback {
public:
trezor_debug_callback()=default;
explicit trezor_debug_callback(std::shared_ptr<Transport> & debug_transport);

void on_button_request();
void on_pin_request(epee::wipeable_string &pin);
void on_passphrase_request(bool on_device, epee::wipeable_string &passphrase);
void on_passphrase_state_request(const std::string &state);
void on_disconnect();
protected:
std::shared_ptr<DebugLink> m_debug_link;
};

#endif

/**
* TREZOR device template with basic functions
*/
@@ -77,6 +98,13 @@ namespace trezor {

cryptonote::network_type network_type;

#ifdef WITH_TREZOR_DEBUGGING
std::shared_ptr<trezor_debug_callback> m_debug_callback;
bool m_debug;

void setup_debug();
#endif

//
// Internal methods
//
@@ -103,7 +131,7 @@ namespace trezor {
* @throws UnexpectedMessageException if the response message type is different than expected.
* Exception contains message type and the message itself.
*/
template<class t_message>
template<class t_message=google::protobuf::Message>
std::shared_ptr<t_message>
client_exchange(const std::shared_ptr<const google::protobuf::Message> &req,
const boost::optional<messages::MessageType> & resp_type = boost::none,
@@ -229,6 +257,12 @@ namespace trezor {
return m_features;
}

uint64_t get_version() const {
CHECK_AND_ASSERT_THROW_MES(m_features, "Features not loaded");
CHECK_AND_ASSERT_THROW_MES(m_features->has_major_version() && m_features->has_minor_version() && m_features->has_patch_version(), "Invalid Trezor firmware version information");
return pack_version(m_features->major_version(), m_features->minor_version(), m_features->patch_version());
}

void set_derivation_path(const std::string &deriv_path) override;

/* ======================================================================= */
@@ -268,6 +302,23 @@ namespace trezor {
void on_pin_request(GenericMessage & resp, const messages::common::PinMatrixRequest * msg);
void on_passphrase_request(GenericMessage & resp, const messages::common::PassphraseRequest * msg);
void on_passphrase_state_request(GenericMessage & resp, const messages::common::PassphraseStateRequest * msg);

#ifdef WITH_TREZOR_DEBUGGING
void set_debug(bool debug){
m_debug = debug;
}

void set_debug_callback(std::shared_ptr<trezor_debug_callback> & debug_callback){
m_debug_callback = debug_callback;
}

void wipe_device();
void init_device();
void load_device(const std::string & mnemonic, const std::string & pin="", bool passphrase_protection=false,
const std::string & label="test", const std::string & language="english",
bool skip_checksum=false, bool expand=false);

#endif
};

#endif
Oops, something went wrong.

0 comments on commit 5ea1790

Please sign in to comment.
You can’t perform that action at this time.