aboutsummaryrefslogtreecommitdiff
path: root/src/device_trezor/device_trezor.cpp
diff options
context:
space:
mode:
authorDusan Klinec <dusan.klinec@gmail.com>2018-11-28 22:22:11 +0100
committerDusan Klinec <dusan.klinec@gmail.com>2018-12-04 20:12:03 +0100
commitd71f89e2a26720021f7509f8c1eee87645f48529 (patch)
tree9086c377f1e47f862e064251a92f8b260f21540a /src/device_trezor/device_trezor.cpp
parentdevice/trezor: python2 compatibility - bundle dependencies (diff)
downloadmonero-d71f89e2a26720021f7509f8c1eee87645f48529.tar.xz
device/trezor: device/trezor: correct device initialization, status check
- checks if the device is in the correct usable state - implements check for the v2.0.9 firmware which does not support payment IDs - simple transacttion check, payment id fmt consistency - minor fixes, refactoring, webusb session counting fix
Diffstat (limited to 'src/device_trezor/device_trezor.cpp')
-rw-r--r--src/device_trezor/device_trezor.cpp77
1 files changed, 67 insertions, 10 deletions
diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp
index 5096fcea8..8868fb995 100644
--- a/src/device_trezor/device_trezor.cpp
+++ b/src/device_trezor/device_trezor.cpp
@@ -121,7 +121,8 @@ namespace trezor {
const boost::optional<cryptonote::network_type> & network_type){
AUTO_LOCK_CMD();
require_connected();
- test_ping();
+ device_state_reset_unsafe();
+ require_initialized();
auto req = std::make_shared<messages::monero::MoneroGetAddress>();
this->set_msg_addr<messages::monero::MoneroGetAddress>(req.get(), path, network_type);
@@ -136,7 +137,8 @@ namespace trezor {
const boost::optional<cryptonote::network_type> & network_type){
AUTO_LOCK_CMD();
require_connected();
- test_ping();
+ device_state_reset_unsafe();
+ require_initialized();
auto req = std::make_shared<messages::monero::MoneroGetWatchKey>();
this->set_msg_addr<messages::monero::MoneroGetWatchKey>(req.get(), path, network_type);
@@ -152,7 +154,8 @@ namespace trezor {
{
AUTO_LOCK_CMD();
require_connected();
- test_ping();
+ device_state_reset_unsafe();
+ require_initialized();
std::shared_ptr<messages::monero::MoneroKeyImageExportInitRequest> req;
@@ -238,12 +241,11 @@ namespace trezor {
cpend.construction_data = cdata.tx_data;
// Transaction check
- cryptonote::blobdata tx_blob;
- cryptonote::transaction tx_deserialized;
- bool r = cryptonote::t_serializable_object_to_blob(cpend.tx, tx_blob);
- CHECK_AND_ASSERT_THROW_MES(r, "Transaction serialization failed");
- r = cryptonote::parse_and_validate_tx_from_blob(tx_blob, tx_deserialized);
- CHECK_AND_ASSERT_THROW_MES(r, "Transaction deserialization failed");
+ try {
+ transaction_check(cdata, aux_data);
+ } catch(const std::exception &e){
+ throw exc::ProtocolException(std::string("Transaction verification failed: ") + e.what());
+ }
std::string key_images;
bool all_are_txin_to_key = std::all_of(cdata.tx.vin.begin(), cdata.tx.vin.end(), [&](const cryptonote::txin_v& s_e) -> bool
@@ -283,7 +285,8 @@ namespace trezor {
{
AUTO_LOCK_CMD();
require_connected();
- test_ping();
+ device_state_reset_unsafe();
+ require_initialized();
CHECK_AND_ASSERT_THROW_MES(idx < unsigned_tx.txes.size(), "Invalid transaction index");
signer = std::make_shared<protocol::tx::Signer>(wallet, &unsigned_tx, idx, &aux_data);
@@ -294,6 +297,7 @@ namespace trezor {
// Step: Init
auto init_msg = signer->step_init();
this->set_msg_addr(init_msg.get());
+ transaction_pre_check(init_msg);
auto response = this->client_exchange<messages::monero::MoneroTransactionInitAck>(init_msg);
signer->step_init_ack(response);
@@ -351,6 +355,59 @@ namespace trezor {
signer->step_final_ack(ack_final);
}
+ void device_trezor::transaction_pre_check(std::shared_ptr<messages::monero::MoneroTransactionInitRequest> init_msg)
+ {
+ CHECK_AND_ASSERT_THROW_MES(init_msg, "TransactionInitRequest is empty");
+ CHECK_AND_ASSERT_THROW_MES(init_msg->has_tsx_data(), "TransactionInitRequest has no transaction data");
+ 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){
+ // 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)) {
+ throw exc::TrezorException("Trezor firmware 2.0.9 and lower does not support transactions with short payment IDs or integrated addresses. Please update.");
+ }
+ }
+ }
+
+ void device_trezor::transaction_check(const protocol::tx::TData & tdata, const hw::tx_aux_data & aux_data)
+ {
+ // Simple serialization check
+ cryptonote::blobdata tx_blob;
+ cryptonote::transaction tx_deserialized;
+ bool r = cryptonote::t_serializable_object_to_blob(tdata.tx, tx_blob);
+ CHECK_AND_ASSERT_THROW_MES(r, "Transaction serialization failed");
+ r = cryptonote::parse_and_validate_tx_from_blob(tx_blob, tx_deserialized);
+ CHECK_AND_ASSERT_THROW_MES(r, "Transaction deserialization failed");
+
+ // Extras check
+ std::vector<cryptonote::tx_extra_field> tx_extra_fields;
+ cryptonote::tx_extra_nonce nonce;
+
+ r = cryptonote::parse_tx_extra(tdata.tx.extra, tx_extra_fields);
+ CHECK_AND_ASSERT_THROW_MES(r, "tx.extra parsing failed");
+
+ const bool nonce_required = tdata.tsx_data.has_payment_id() && tdata.tsx_data.payment_id().size() > 0;
+ const bool has_nonce = cryptonote::find_tx_extra_field_by_type(tx_extra_fields, nonce);
+ CHECK_AND_ASSERT_THROW_MES(has_nonce == nonce_required, "Transaction nonce presence inconsistent");
+
+ if (nonce_required){
+ const std::string & payment_id = tdata.tsx_data.payment_id();
+ if (payment_id.size() == 32){
+ crypto::hash payment_id_long{};
+ CHECK_AND_ASSERT_THROW_MES(cryptonote::get_payment_id_from_tx_extra_nonce(nonce.nonce, payment_id_long), "Long payment ID not present");
+
+ } else if (payment_id.size() == 8){
+ crypto::hash8 payment_id_short{};
+ CHECK_AND_ASSERT_THROW_MES(cryptonote::get_encrypted_payment_id_from_tx_extra_nonce(nonce.nonce, payment_id_short), "Short payment ID not present");
+ }
+ }
+ }
+
#else //WITH_DEVICE_TREZOR
void register_all(std::map<std::string, std::unique_ptr<device>> &registry) {