diff --git a/src/device/device.hpp b/src/device/device.hpp index b47460472..db489ff0c 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -80,6 +80,9 @@ namespace hw { class device { + protected: + std::string name; + public: device() {} @@ -87,12 +90,12 @@ namespace hw { virtual ~device() {} explicit virtual operator bool() const = 0; - - static const int SIGNATURE_REAL = 0; - static const int SIGNATURE_FAKE = 1; - - - std::string name; + enum device_mode { + NONE, + TRANSACTION_CREATE_REAL, + TRANSACTION_CREATE_FAKE, + TRANSACTION_PARSE + }; /* ======================================================================= */ /* SETUP/TEARDOWN */ @@ -104,7 +107,18 @@ namespace hw { virtual bool release() = 0; virtual bool connect(void) = 0; - virtual bool disconnect() = 0; + virtual bool disconnect(void) = 0; + + virtual bool set_mode(device_mode mode) = 0; + + + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + virtual void lock(void) = 0; + virtual void unlock(void) = 0; + virtual bool try_lock(void) = 0; + /* ======================================================================= */ /* WALLET & ADDRESS */ @@ -158,8 +172,6 @@ namespace hw { virtual bool open_tx(crypto::secret_key &tx_key) = 0; - virtual bool set_signature_mode(unsigned int sig_mode) = 0; - virtual bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) = 0; bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) { @@ -183,6 +195,12 @@ namespace hw { virtual bool close_tx(void) = 0; } ; + struct reset_mode { + device& hwref; + reset_mode(hw::device& dev) : hwref(dev) { } + ~reset_mode() { hwref.set_mode(hw::device::NONE);} + }; + device& get_device(const std::string device_descriptor) ; } diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index d63dafe9e..96838a289 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -81,6 +81,20 @@ namespace hw { dfns(); } + bool device_default::set_mode(device_mode mode) { + return true; + } + + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + + void device_default::lock() { } + + bool device_default::try_lock() { return true; } + + void device_default::unlock() { } + /* ======================================================================= */ /* WALLET & ADDRESS */ /* ======================================================================= */ @@ -262,10 +276,6 @@ namespace hw { return true; } - bool device_default::set_signature_mode(unsigned int sig_mode) { - return true; - } - bool device_default::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) { crypto::key_derivation derivation; crypto::hash hash; diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp index 02faeba0c..53942f53a 100644 --- a/src/device/device_default.hpp +++ b/src/device/device_default.hpp @@ -58,7 +58,16 @@ namespace hw { bool connect(void) override; bool disconnect() override; + + bool set_mode(device_mode mode) override; + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + void lock(void) override; + void unlock(void) override; + bool try_lock(void) override; + /* ======================================================================= */ /* WALLET & ADDRESS */ /* ======================================================================= */ @@ -97,9 +106,6 @@ namespace hw { bool open_tx(crypto::secret_key &tx_key) override; - //bool get_additional_key(const bool subaddr, cryptonote::keypair &additional_txkey) override; - bool set_signature_mode(unsigned int sig_mode) override; - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override; bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec) override; diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index b3c0035a1..ee1497438 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -33,7 +33,8 @@ #include "cryptonote_basic/account.h" #include "cryptonote_basic/subaddress_index.h" - +#include +#include namespace hw { @@ -57,8 +58,8 @@ namespace hw { #define ASSERT_T0(exp) CHECK_AND_ASSERT_THROW_MES(exp, "Protocol assert failure: "#exp ) ; #ifdef DEBUG_HWDEVICE - crypto::secret_key viewkey; - crypto::secret_key spendkey; + crypto::secret_key dbg_viewkey; + crypto::secret_key dbg_spendkey; #endif /* ===================================================================== */ @@ -118,7 +119,14 @@ namespace hw { #endif /* ===================================================================== */ - /* === Device ==== */ + /* === Internal Helpers ==== */ + /* ===================================================================== */ + static bool is_fake_view_key(const crypto::secret_key &sec) { + return sec == crypto::null_skey; + } + + /* ===================================================================== */ + /* === Device ==== */ /* ===================================================================== */ static int device_id = 0; @@ -196,6 +204,8 @@ namespace hw { this->hCard = 0; this->hContext = 0; this->reset_buffer(); + this->mode = NONE; + this->has_view_key = false; MDEBUG( "Device "<id <<" Created"); } @@ -204,14 +214,51 @@ namespace hw { MDEBUG( "Device "<id <<" Destroyed"); } + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + + //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*/ \ + boost::lock(device_locker, command_locker); \ + /* make sure both already-locked mutexes are unlocked at the end of scope */ \ + boost::lock_guard lock1(device_locker, boost::adopt_lock); \ + boost::lock_guard lock2(command_locker, boost::adopt_lock) + + //lock the device for a long sequence + void device_ledger::lock(void) { + MDEBUG( "Ask for LOCKING for device "<name << " in thread "); + device_locker.lock(); + MDEBUG( "Device "<name << " LOCKed"); + } + + //lock the device for a long sequence + bool device_ledger::try_lock(void) { + MDEBUG( "Ask for LOCKING(try) for device "<name << " in thread "); + bool r = device_locker.try_lock(); + if (r) { + MDEBUG( "Device "<name << " LOCKed(try)"); + } else { + MDEBUG( "Device "<name << " not LOCKed(try)"); + } + return r; + } + + //lock the device for a long sequence + void device_ledger::unlock(void) { + try { + MDEBUG( "Ask for UNLOCKING for device "<name << " in thread "); + } catch (...) { + } + device_locker.unlock(); + MDEBUG( "Device "<name << " UNLOCKed"); + } /* ======================================================================= */ /* MISC */ /* ======================================================================= */ bool device_ledger::reset() { - - lock_device(); - try { int offset; reset_buffer(); @@ -227,12 +274,7 @@ namespace hw { this->buffer_send[4] = offset-5; this->length_send = offset; this->exchange(); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } unsigned int device_ledger::exchange(unsigned int ok, unsigned int mask) { @@ -261,30 +303,6 @@ namespace hw { memset(this->buffer_recv, 0, BUFFER_RECV_SIZE); } - void device_ledger::lock_device() { - MDEBUG( "Ask for LOCKING for device "<id); - device_locker.lock(); - MDEBUG( "Device "<id << " LOCKed"); - } - void device_ledger::unlock_device() { - try { - MDEBUG( "Ask for UNLOCKING for device "<id); - } catch (...) { - } - device_locker.unlock(); - MDEBUG( "Device "<id << " UNLOCKed"); - } - void device_ledger::lock_tx() { - MDEBUG( "Ask for LOCKING for TX "<id); - //tx_locker.lock(); - MDEBUG( "TX "<id << " LOCKed"); - } - void device_ledger::unlock_tx() { - MDEBUG( "Ask for UNLOCKING for TX "<id); - //tx_locker.unlock(); - MDEBUG( "TX "<id << " UNLOCKed"); - } - /* ======================================================================= */ /* SETUP/TEARDOWN */ /* ======================================================================= */ @@ -394,10 +412,10 @@ namespace hw { #ifdef DEBUG_HWDEVICE cryptonote::account_public_address pubkey; this->get_public_address(pubkey); + #endif crypto::secret_key vkey; crypto::secret_key skey; this->get_secret_keys(vkey,skey); - #endif return rv==SCARD_S_SUCCESS; } @@ -411,16 +429,55 @@ namespace hw { return true; } + bool device_ledger::set_mode(device_mode mode) { + AUTO_LOCK_CMD(); + + int offset; + + reset_buffer(); + + switch(mode) { + case TRANSACTION_CREATE_REAL: + case TRANSACTION_CREATE_FAKE: + this->buffer_send[0] = 0x00; + this->buffer_send[1] = INS_SET_SIGNATURE_MODE; + this->buffer_send[2] = 0x01; + this->buffer_send[3] = 0x00; + this->buffer_send[4] = 0x00; + offset = 5; + //options + this->buffer_send[offset] = 0x00; + offset += 1; + //account + this->buffer_send[offset] = mode; + offset += 1; + + this->buffer_send[4] = offset-5; + this->length_send = offset; + this->exchange(); + + this->mode = mode; + break; + + case TRANSACTION_PARSE: + case NONE: + this->mode = mode; + break; + default: + CHECK_AND_ASSERT_THROW_MES(false, " device_ledger::set_mode(unsigned int mode): invalid mode: "<buffer_recv, 32); memmove(pubkey.m_spend_public_key.data, this->buffer_recv+32, 32); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + + return true; } - bool device_ledger::get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) { - memset(viewkey.data, 0x00, 32); - memset(spendkey.data, 0xFF, 32); + bool device_ledger::get_secret_keys(crypto::secret_key &vkey , crypto::secret_key &skey) { + AUTO_LOCK_CMD(); + + //secret key are represented as fake key on the wallet side + memset(vkey.data, 0x00, 32); + memset(skey.data, 0xFF, 32); - #ifdef DEBUG_HWDEVICE - lock_device(); - try { //spcialkey, normal conf handled in decrypt int offset; reset_buffer(); @@ -473,21 +526,26 @@ namespace hw { this->length_send = offset; this->exchange(); - //clear key - memmove(ledger::viewkey.data, this->buffer_recv+64, 32); - memmove(ledger::spendkey.data, this->buffer_recv+96, 32); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - #endif - return true; + //View key is retrievied, if allowed, to speed up blockchain parsing + memmove(this->viewkey.data, this->buffer_recv+0, 32); + if (is_fake_view_key(this->viewkey)) { + MDEBUG("Have Not view key"); + this->has_view_key = false; + } else { + MDEBUG("Have view key"); + this->has_view_key = true; + } + + #ifdef DEBUG_HWDEVICE + memmove(dbg_viewkey.data, this->buffer_recv+0, 32); + memmove(dbg_spendkey.data, this->buffer_recv+32, 32); + #endif + + return true; } bool device_ledger::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key) { - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; #ifdef DEBUG_HWDEVICE @@ -519,11 +577,6 @@ namespace hw { hw::ledger::check32("generate_chacha_key_prehashed", "key", (char*)key_x.data(), (char*)key.data()); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } return true; } @@ -532,15 +585,15 @@ namespace hw { /* ======================================================================= */ bool device_ledger::derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub){ - - lock_device(); - try { - int offset =0; - unsigned char options = 0; - + AUTO_LOCK_CMD(); #ifdef DEBUG_HWDEVICE const crypto::public_key pub_x = pub; - const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); + crypto::key_derivation derivation_x; + if ((this->mode == TRANSACTION_PARSE) && has_view_key) { + derivation_x = derivation; + } else { + derivation_x = hw::ledger::decrypt(derivation); + } const std::size_t output_index_x = output_index; crypto::public_key derived_pub_x; hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] pub ", pub_x.data, 32); @@ -550,10 +603,17 @@ namespace hw { hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32); #endif + if ((this->mode == TRANSACTION_PARSE) && has_view_key) { + //If we are in TRANSACTION_PARSE, the given derivation has been retrieved uncrypted (wihtout the help + //of the device), so continue that way. + MDEBUG( "derive_subaddress_public_key : PARSE mode with known viewkey"); + crypto::derive_subaddress_public_key(pub, derivation, output_index,derived_pub); + } else { + + int offset =0; + reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_DERIVE_SUBADDRESS_PUBLIC_KEY; this->buffer_send[2] = 0x00; @@ -561,7 +621,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //pub memmove(this->buffer_send+offset, pub.data, 32); @@ -582,34 +642,27 @@ namespace hw { //pub key memmove(derived_pub.data, &this->buffer_recv[0], 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); - #endif - - unlock_device(); - }catch (...) { - unlock_device(); - throw; } + #ifdef DEBUG_HWDEVICE + hw::ledger::check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); + #endif + return true; } crypto::public_key device_ledger::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { - crypto::public_key D; - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + crypto::public_key D; + int offset; #ifdef DEBUG_HWDEVICE const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); const cryptonote::subaddress_index index_x = index; crypto::public_key D_x; - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data,32); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_spend_secret_key", keys_x.m_spend_secret_key.data,32); + hw::ledger::log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data,32); + hw::ledger::log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_spend_secret_key", keys_x.m_spend_secret_key.data,32); hw::ledger::log_message ("get_subaddress_spend_public_key: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor)); - this->controle_device->get_subaddress_spend_public_key(keys_x, index_x, D_x); + D_x = this->controle_device->get_subaddress_spend_public_key(keys_x, index_x); hw::ledger::log_hexbuffer("get_subaddress_spend_public_key: [[OUT]] derivation ", D_x.data, 32); #endif @@ -644,12 +697,7 @@ namespace hw { hw::ledger::check32("get_subaddress_spend_public_key", "D", D_x.data, D.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return D; + return D; } std::vector device_ledger::get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) { @@ -665,24 +713,22 @@ namespace hw { } cryptonote::account_public_address device_ledger::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { - cryptonote::account_public_address address; - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + cryptonote::account_public_address address; + int offset; #ifdef DEBUG_HWDEVICE const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); const cryptonote::subaddress_index index_x = index; cryptonote::account_public_address address_x; - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_public_key", keys_x.m_account_address.m_view_public_key.data, 32); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_spend_public_key", keys_x.m_account_address.m_spend_public_key.data, 32); + hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); + hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_view_public_key", keys_x.m_account_address.m_view_public_key.data, 32); + hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); + hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_spend_public_key", keys_x.m_account_address.m_spend_public_key.data, 32); hw::ledger::log_message ("get_subaddress: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor)); - this->controle_device->get_subaddress(keys_x, index_x, address_x); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_public_key ", address_x.m_view_public_key.data, 32); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_spend_public_key", address_x.m_spend_public_key.data, 32); + address_x = this->controle_device->get_subaddress(keys_x, index_x); + hw::ledger::log_hexbuffer("get_subaddress: [[OUT]] keys.m_view_public_key ", address_x.m_view_public_key.data, 32); + hw::ledger::log_hexbuffer("get_subaddress: [[OUT]] keys.m_spend_public_key", address_x.m_spend_public_key.data, 32); #endif if (index.is_zero()) { @@ -717,20 +763,13 @@ namespace hw { hw::ledger::check32("get_subaddress", "address.m_spend_public_key.data", address_x.m_spend_public_key.data, address.m_spend_public_key.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return address; + return address; } crypto::secret_key device_ledger::get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) { - crypto::secret_key sub_sec; - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + crypto::secret_key sub_sec; + int offset; #ifdef DEBUG_HWDEVICE const crypto::secret_key sec_x = hw::ledger::decrypt(sec); @@ -738,7 +777,7 @@ namespace hw { crypto::secret_key sub_sec_x; hw::ledger::log_message ("get_subaddress_secret_key: [[IN]] index ", std::to_string(index.major)+"."+std::to_string(index.minor)); hw::ledger::log_hexbuffer("get_subaddress_secret_key: [[IN]] sec ", sec_x.data, 32); - this->controle_device->get_subaddress_secret_key(sec_x, index_x, sub_sec_x); + sub_sec_x = this->controle_device->get_subaddress_secret_key(sec_x, index_x); hw::ledger::log_hexbuffer("get_subaddress_secret_key: [[OUT]] sub_sec", sub_sec_x.data, 32); #endif @@ -751,7 +790,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //sec memmove(this->buffer_send+offset, sec.data, 32); @@ -772,12 +811,7 @@ namespace hw { hw::ledger::check32("get_subaddress_secret_key", "sub_sec", sub_sec_x.data, sub_sec_clear.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return sub_sec; + return sub_sec; } /* ======================================================================= */ @@ -785,10 +819,9 @@ namespace hw { /* ======================================================================= */ bool device_ledger::verify_keys(const crypto::secret_key &secret_key, const crypto::public_key &public_key) { - lock_device(); - try { - int offset =0,sw; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset, sw; + reset_buffer(); this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_VERIFY_KEY; @@ -816,20 +849,12 @@ namespace hw { this->buffer_recv[2] << 8 | this->buffer_recv[3] << 0 ; - unlock_device(); return verified == 1; - }catch (...) { - unlock_device(); - throw; - } - return false; } bool device_ledger::scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const rct::key P_x = P; @@ -843,8 +868,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_SECRET_SCAL_MUL_KEY; this->buffer_send[2] = 0x00; @@ -852,7 +875,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //pub memmove(this->buffer_send+offset, P.bytes, 32); @@ -873,19 +896,12 @@ namespace hw { hw::ledger::check32("scalarmultKey", "mulkey", (char*)aP_x.bytes, (char*)aP.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::scalarmultBase(rct::key &aG, const rct::key &a) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const rct::key a_x = hw::ledger::decrypt(a); @@ -897,8 +913,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_SECRET_SCAL_MUL_BASE; this->buffer_send[2] = 0x00; @@ -906,7 +920,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //sec memmove(this->buffer_send+offset, a.bytes, 32); @@ -923,20 +937,12 @@ namespace hw { hw::ledger::check32("scalarmultBase", "mulkey", (char*)aG_x.bytes, (char*)aG.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::sc_secret_add( crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) { - - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const crypto::secret_key a_x = hw::ledger::decrypt(a); @@ -947,8 +953,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_SECRET_KEY_ADD; this->buffer_send[2] = 0x00; @@ -956,7 +960,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //sec key memmove(this->buffer_send+offset, a.data, 32); @@ -977,23 +981,16 @@ namespace hw { hw::ledger::check32("sc_secret_add", "r", r_x.data, r_clear.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } crypto::secret_key device_ledger::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover) { - if (recover) { - throw std::runtime_error("device generate key does not support recover"); - } + AUTO_LOCK_CMD(); + if (recover) { + throw std::runtime_error("device generate key does not support recover"); + } - lock_device(); - try { - int offset =0; - unsigned char options = 0; + int offset; #ifdef DEBUG_HWDEVICE bool recover_x = recover; @@ -1004,8 +1001,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_GENERATE_KEYPAIR; this->buffer_send[2] = 0x00; @@ -1013,7 +1008,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; this->buffer_send[4] = offset-5; @@ -1031,20 +1026,13 @@ namespace hw { hw::ledger::check32("generate_keys", "pub", pub_x.data, pub.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return sec; + return sec; } bool device_ledger::generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + bool r = false; #ifdef DEBUG_HWDEVICE const crypto::public_key pub_x = pub; @@ -1056,6 +1044,17 @@ namespace hw { hw::ledger::log_hexbuffer("generate_key_derivation: [[OUT]] derivation", derivation_x.data, 32); #endif + if ((this->mode == TRANSACTION_PARSE) && has_view_key) { + //A derivation is resquested in PASRE mode and we have the view key, + //so do that wihtout the device and return the derivation unencrypted. + MDEBUG( "generate_key_derivation : PARSE mode with known viewkey"); + //Note derivation in PARSE mode can only happen with viewkey, so assert it! + assert(is_fake_view_key(sec)); + r = crypto::generate_key_derivation(pub, this->viewkey, derivation); + } else { + + int offset; + reset_buffer(); this->buffer_send[0] = 0x00; @@ -1065,7 +1064,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //pub memmove(this->buffer_send+offset, pub.data, 32); @@ -1080,25 +1079,24 @@ namespace hw { //derivattion data memmove(derivation.data, &this->buffer_recv[0], 32); - - #ifdef DEBUG_HWDEVICE - crypto::key_derivation derivation_clear = hw::ledger::decrypt(derivation); - hw::ledger::check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data); - #endif - - unlock_device(); - }catch (...) { - unlock_device(); - throw; + r = true; } - return true; + #ifdef DEBUG_HWDEVICE + crypto::key_derivation derivation_clear ; + if ((this->mode == TRANSACTION_PARSE) && has_view_key) { + derivation_clear = derivation; + }else { + derivation_clear = hw::ledger::decrypt(derivation); + } + hw::ledger::check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data); + #endif + + return r; } bool device_ledger::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) { - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; - unsigned char options; #ifdef DEBUG_HWDEVICE const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); @@ -1112,8 +1110,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_DERIVATION_TO_SCALAR; this->buffer_send[2] = 0x00; @@ -1121,7 +1117,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //derivattion memmove(this->buffer_send+offset, derivation.data, 32); @@ -1145,19 +1141,12 @@ namespace hw { hw::ledger::check32("derivation_to_scalar", "res", res_x.data, res_clear.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) { - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; - unsigned char options; #ifdef DEBUG_HWDEVICE const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); @@ -1173,8 +1162,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_DERIVE_SECRET_KEY; this->buffer_send[2] = 0x00; @@ -1182,7 +1169,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //derivation memmove(this->buffer_send+offset, derivation.data, 32); @@ -1209,20 +1196,13 @@ namespace hw { hw::ledger::check32("derive_secret_key", "derived_sec", derived_sec_x.data, derived_sec_clear.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub){ - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; - unsigned char options; - + #ifdef DEBUG_HWDEVICE const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); const std::size_t output_index_x = output_index; @@ -1237,8 +1217,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_DERIVE_PUBLIC_KEY; this->buffer_send[2] = 0x00; @@ -1246,7 +1224,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //derivation memmove(this->buffer_send+offset, derivation.data, 32); @@ -1272,19 +1250,12 @@ namespace hw { hw::ledger::check32("derive_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) { - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; - unsigned char options; #ifdef DEBUG_HWDEVICE const crypto::secret_key sec_x = hw::ledger::decrypt(sec); @@ -1299,8 +1270,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_SECRET_KEY_TO_PUBLIC_KEY; this->buffer_send[2] = 0x00; @@ -1308,7 +1277,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //sec key memmove(this->buffer_send+offset, sec.data, 32); @@ -1325,19 +1294,12 @@ namespace hw { hw::ledger::check32("secret_key_to_public_key", "pub", pub_x.data, pub.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image){ - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; - unsigned char options; #ifdef DEBUG_HWDEVICE const crypto::public_key pub_x = pub; @@ -1351,8 +1313,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_GEN_KEY_IMAGE; this->buffer_send[2] = 0x00; @@ -1360,7 +1320,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //pub memmove(this->buffer_send+offset, pub.data, 32); @@ -1380,12 +1340,7 @@ namespace hw { hw::ledger::check32("generate_key_image", "image", image_x.data, image.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } /* ======================================================================= */ @@ -1393,12 +1348,9 @@ namespace hw { /* ======================================================================= */ bool device_ledger::open_tx(crypto::secret_key &tx_key) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; - lock_tx(); reset_buffer(); key_map.clear(); @@ -1423,57 +1375,19 @@ namespace hw { this->exchange(); memmove(tx_key.data, &this->buffer_recv[32], 32); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; - } - - bool device_ledger::set_signature_mode(unsigned int sig_mode) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; - - reset_buffer(); - - this->buffer_send[0] = 0x00; - this->buffer_send[1] = INS_SET_SIGNATURE_MODE; - this->buffer_send[2] = 0x01; - this->buffer_send[3] = 0x00; - this->buffer_send[4] = 0x00; - offset = 5; - //options - this->buffer_send[offset] = 0x00; - offset += 1; - //account - this->buffer_send[offset] = sig_mode; - offset += 1; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + + return true; } bool device_ledger::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const crypto::public_key public_key_x = public_key; const crypto::secret_key secret_key_x = hw::ledger::decrypt(secret_key); crypto::hash8 payment_id_x = payment_id; - this->controle_device->encrypt_payment_id(public_key_x, secret_key_x, payment_id_x); + this->controle_device->encrypt_payment_id(payment_id_x, public_key_x, secret_key_x); #endif reset_buffer(); @@ -1506,32 +1420,19 @@ namespace hw { hw::ledger::check8("stealth", "payment_id", payment_id_x.data, payment_id.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index, const rct::key &amount_key, const crypto::public_key &out_eph_public_key) { - lock_device(); - try { + AUTO_LOCK_CMD(); key_map.add(ABPkeys(rct::pk2rct(Aout),rct::pk2rct(Bout), is_subaddress, real_output_index, rct::pk2rct(out_eph_public_key), amount_key)); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & AKout) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const rct::key AKout_x = hw::ledger::decrypt(AKout); @@ -1574,19 +1475,12 @@ namespace hw { hw::ledger::log_hexbuffer("Blind AKV input", (char*)&this->buffer_recv[64], 3*32); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::ecdhDecode(rct::ecdhTuple & masked, const rct::key & AKout) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const rct::key AKout_x = hw::ledger::decrypt(AKout); @@ -1627,21 +1521,13 @@ namespace hw { hw::ledger::check32("ecdhDecode", "mask", (char*)masked_x.mask.bytes,(char*) masked.mask.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) { - - lock_device(); - try { - unsigned char options = 0; + AUTO_LOCK_CMD(); unsigned int data_offset, C_offset, kv_offset, i; const char *data; @@ -1834,21 +1720,15 @@ namespace hw { hw::ledger::check32("mlsag_prehash", "prehash", (char*)prehash_x.bytes, (char*)prehash.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &II) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; + unsigned char options; #ifdef DEBUG_HWDEVICE const rct::key H_x = H; @@ -1897,19 +1777,13 @@ namespace hw { hw::ledger::check32("mlsag_prepare", "II", (char*)II_x.bytes, (char*)II.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::mlsag_prepare(rct::key &a, rct::key &aG) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; + unsigned char options; #ifdef DEBUG_HWDEVICE rct::key a_x; @@ -1941,19 +1815,13 @@ namespace hw { hw::ledger::check32("mlsag_prepare", "AG", (char*)aG_x.bytes, (char*)aG.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::mlsag_hash(const rct::keyV &long_message, rct::key &c) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; + unsigned char options; size_t cnt; #ifdef DEBUG_HWDEVICE @@ -1991,20 +1859,12 @@ namespace hw { hw::ledger::check32("mlsag_hash", "c", (char*)c_x.bytes, (char*)c.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; - + return true; } bool device_ledger::mlsag_sign(const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; CHECK_AND_ASSERT_THROW_MES(dsRows<=rows, "dsRows greater than rows"); CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "xx size does not match rows"); @@ -2061,19 +1921,12 @@ namespace hw { } #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::close_tx() { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; reset_buffer(); @@ -2091,13 +1944,7 @@ namespace hw { this->length_send = offset; this->exchange(); - unlock_tx(); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } /* ---------------------------------------------------------- */ diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index e06c5f72c..652cfb34b 100644 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -32,11 +32,11 @@ #include #include -#include #include "device.hpp" #include #include - +#include +#include namespace hw { @@ -80,13 +80,11 @@ namespace hw { class device_ledger : public hw::device { private: - mutable std::mutex device_locker; - mutable std::mutex tx_locker; - void lock_device() ; - void unlock_device() ; - void lock_tx() ; - void unlock_tx() ; - + // Locker for concurrent access + mutable boost::recursive_mutex device_locker; + mutable boost::mutex command_locker; + + //PCSC management std::string full_name; SCARDCONTEXT hContext; SCARDHANDLE hCard; @@ -95,15 +93,21 @@ namespace hw { DWORD length_recv; BYTE buffer_recv[BUFFER_RECV_SIZE]; unsigned int id; - - Keymap key_map; - - void logCMD(void); void logRESP(void); unsigned int exchange(unsigned int ok=0x9000, unsigned int mask=0xFFFF); void reset_buffer(void); + // hw running mode + device_mode mode; + // map public destination key to ephemeral destination key + Keymap key_map; + + // To speed up blockchain parsing the view key maybe handle here. + crypto::secret_key viewkey; + bool has_view_key; + + //extra debug #ifdef DEBUG_HWDEVICE device *controle_device; #endif @@ -130,6 +134,15 @@ namespace hw { bool connect(void) override; bool disconnect() override; + bool set_mode(device_mode mode) override; + + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + void lock(void) override; + void unlock(void) override; + bool try_lock(void) override; + /* ======================================================================= */ /* WALLET & ADDRESS */ /* ======================================================================= */ @@ -168,8 +181,6 @@ namespace hw { bool open_tx(crypto::secret_key &tx_key) override; - bool set_signature_mode(unsigned int sig_mode) override; - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override; bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec) override; @@ -190,10 +201,9 @@ namespace hw { }; - #ifdef DEBUG_HWDEVICE - extern crypto::secret_key viewkey; - extern crypto::secret_key spendkey; + extern crypto::secret_key dbg_viewkey; + extern crypto::secret_key dbg_spendkey; #endif #endif //WITH_DEVICE_LEDGER diff --git a/src/device/log.cpp b/src/device/log.cpp index a2ad0f4f4..cbbcfc953 100644 --- a/src/device/log.cpp +++ b/src/device/log.cpp @@ -56,8 +56,8 @@ namespace hw { } #ifdef DEBUG_HWDEVICE - extern crypto::secret_key viewkey; - extern crypto::secret_key spendkey; + extern crypto::secret_key dbg_viewkey; + extern crypto::secret_key dbg_spendkey; void decrypt(char* buf, size_t len) { @@ -69,7 +69,7 @@ namespace hw { if (buf[i] != 0) break; } if (i == 32) { - memmove(buf, hw::ledger::viewkey.data, 32); + memmove(buf, hw::ledger::dbg_viewkey.data, 32); return; } //spend key? @@ -77,7 +77,7 @@ namespace hw { if (buf[i] != (char)0xff) break; } if (i == 32) { - memmove(buf, hw::ledger::spendkey.data, 32); + memmove(buf, hw::ledger::dbg_spendkey.data, 32); return; } } @@ -161,4 +161,4 @@ namespace hw { } #endif //WITH_DEVICE_LEDGER -} \ No newline at end of file +} diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 4e06c4692..b2651026f 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2974,6 +2974,22 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) // create wallet bool r = new_wallet(vm, "Ledger"); CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); + // if no block_height is specified, assume its a new account and start it "now" + if(m_wallet->get_refresh_from_block_height() == 0) { + { + tools::scoped_message_writer wrt = tools::msg_writer(); + wrt << tr("No restore height is specified."); + wrt << tr("Assumed you are creating a new account, restore will be done from current estimated blockchain height."); + wrt << tr("Use --restore-height if you want to restore an already setup account from a specific height"); + } + std::string confirm = input_line(tr("Is this okay? (Y/Yes/N/No): ")); + if (std::cin.eof() || !command_line::is_yes(confirm)) + CHECK_AND_ASSERT_MES(false, false, tr("account creation aborted")); + + m_wallet->set_refresh_from_block_height(m_wallet->estimate_blockchain_height()-1); + m_wallet->explicit_refresh_from_block_height(true); + m_restore_height = m_wallet->get_refresh_from_block_height(); + } } else { @@ -2990,7 +3006,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); } - if (m_restoring && m_generate_from_json.empty()) + if (m_restoring && m_generate_from_json.empty() && m_generate_from_device.empty()) { m_wallet->explicit_refresh_from_block_height(!command_line::is_arg_defaulted(vm, arg_restore_height)); } @@ -3388,7 +3404,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm, try { m_wallet->restore(m_wallet_file, std::move(rc.second).password(), device_name); - message_writer(console_color_white, true) << tr("Generated new on device wallet: ") + message_writer(console_color_white, true) << tr("Generated new wallet on hw device: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); } catch (const std::exception& e) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 7c9a66c26..27310f400 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1007,13 +1007,16 @@ void wallet2::set_unspent(size_t idx) //---------------------------------------------------------------------------------------------------- void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivation &derivation, const std::vector &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const { + hw::device &hwdev = m_account.get_device(); + std::unique_lock hwdev_lock (hwdev); + hwdev.set_mode(hw::device::TRANSACTION_PARSE); if (o.target.type() != typeid(txout_to_key)) { tx_scan_info.error = true; LOG_ERROR("wrong type id in transaction out"); return; } - tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, boost::get(o.target).key, derivation, additional_derivations, i, m_account.get_device()); + tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, boost::get(o.target).key, derivation, additional_derivations, i, hwdev); if(tx_scan_info.received) { tx_scan_info.money_transfered = o.amount; // may be 0 for ringct outputs @@ -1080,9 +1083,15 @@ void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::publi //---------------------------------------------------------------------------------------------------- void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen) { - // In this function, tx (probably) only contains the base information - // (that is, the prunable stuff may or may not be included) + //ensure device is let in NONE mode in any case + hw::device &hwdev = m_account.get_device(); + + std::unique_lock hwdev_lock (hwdev); + hw::reset_mode rst(hwdev); + hwdev_lock.unlock(); + // In this function, tx (probably) only contains the base information + // (that is, the prunable stuff may or may not be included) if (!miner_tx && !pool) process_unconfirmed(txid, tx, height); std::vector outs; @@ -1119,8 +1128,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote tools::threadpool& tpool = tools::threadpool::getInstance(); tools::threadpool::waiter waiter; const cryptonote::account_keys& keys = m_account.get_keys(); - hw::device &hwdev = m_account.get_device(); crypto::key_derivation derivation; + + hwdev_lock.lock(); + hwdev.set_mode(hw::device::TRANSACTION_PARSE); if (!hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation)) { MWARNING("Failed to generate key derivation from tx pubkey, skipping"); @@ -1140,6 +1151,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote additional_derivations.pop_back(); } } + hwdev_lock.unlock(); if (miner_tx && m_refresh_type == RefreshNoCoinbase) { @@ -1161,16 +1173,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote std::ref(tx_scan_info[i]))); } waiter.wait(); - // then scan all outputs from 0 + hwdev_lock.lock(); + hwdev.set_mode(hw::device::NONE); for (size_t i = 0; i < tx.vout.size(); ++i) { THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys()); if (tx_scan_info[i].received) { + hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation); scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); } } + hwdev_lock.unlock(); } } else if (tx.vout.size() > 1 && tools::threadpool::getInstance().get_max_concurrency() > 1) @@ -1181,14 +1196,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote std::ref(tx_scan_info[i]))); } waiter.wait(); + + hwdev_lock.lock(); + hwdev.set_mode(hw::device::NONE); for (size_t i = 0; i < tx.vout.size(); ++i) { THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys()); if (tx_scan_info[i].received) { + hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation); scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); } } + hwdev_lock.unlock(); } else { @@ -1198,7 +1218,11 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys()); if (tx_scan_info[i].received) { + hwdev_lock.lock(); + hwdev.set_mode(hw::device::NONE); + hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation); scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); + hwdev_lock.unlock(); } } } @@ -7259,6 +7283,11 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image, // usable balance. std::vector wallet2::create_transactions_2(std::vector dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra, uint32_t subaddr_account, std::set subaddr_indices, bool trusted_daemon) { + //ensure device is let in NONE mode in any case + hw::device &hwdev = m_account.get_device(); + std::unique_lock hwdev_lock (hwdev); + hw::reset_mode rst(hwdev); + if(m_light_wallet) { // Populate m_transfers light_wallet_get_unspent_outs(); @@ -7476,8 +7505,8 @@ std::vector wallet2::create_transactions_2(std::vector* unused_transfers_indices = &unused_transfers_indices_per_subaddr[0].second; std::vector* unused_dust_indices = &unused_dust_indices_per_subaddr[0].second; - hw::device &hwdev = m_account.get_device(); - hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE); + + hwdev.set_mode(hw::device::TRANSACTION_CREATE_FAKE); while ((!dsts.empty() && dsts[0].amount > 0) || adding_fee || !preferred_inputs.empty() || should_pick_a_second_output(use_rct, txes.back().selected_transfers.size(), *unused_transfers_indices, *unused_dust_indices)) { TX &tx = txes.back(); @@ -7706,7 +7735,7 @@ skip_tx: LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) << " total fee, " << print_money(accumulated_change) << " total change"); - hwdev.set_signature_mode(hw::device::SIGNATURE_REAL); + hwdev.set_mode(hw::device::TRANSACTION_CREATE_REAL); for (std::vector::iterator i = txes.begin(); i != txes.end(); ++i) { TX &tx = *i; @@ -7837,6 +7866,11 @@ std::vector wallet2::create_transactions_single(const crypt std::vector wallet2::create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, std::vector unused_transfers_indices, std::vector unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra, bool trusted_daemon) { + //ensure device is let in NONE mode in any case + hw::device &hwdev = m_account.get_device(); + std::unique_lock hwdev_lock (hwdev); + hw::reset_mode rst(hwdev); + uint64_t accumulated_fee, accumulated_outputs, accumulated_change; struct TX { std::vector selected_transfers; @@ -7869,8 +7903,7 @@ std::vector wallet2::create_transactions_from(const crypton needed_fee = 0; // while we have something to send - hw::device &hwdev = m_account.get_device(); - hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE); + hwdev.set_mode(hw::device::TRANSACTION_CREATE_FAKE); while (!unused_dust_indices.empty() || !unused_transfers_indices.empty()) { TX &tx = txes.back(); @@ -7956,7 +7989,7 @@ std::vector wallet2::create_transactions_from(const crypton LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) << " total fee, " << print_money(accumulated_change) << " total change"); - hwdev.set_signature_mode(hw::device::SIGNATURE_REAL); + hwdev.set_mode(hw::device::TRANSACTION_CREATE_REAL); for (std::vector::iterator i = txes.begin(); i != txes.end(); ++i) { TX &tx = *i;