From aea92f39502683f83ce9598246472e18dd44f298 Mon Sep 17 00:00:00 2001 From: victor-tucci Date: Tue, 13 Jun 2023 16:54:26 +0530 Subject: [PATCH 1/3] Add short_duration for single-unit time printing --- src/common/string_util.cpp | 27 +++++++++++++++++++++++++++ src/common/string_util.h | 5 ++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 97115e4381f..a5caf2b31bd 100755 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -1,5 +1,6 @@ #include "string_util.h" #include +#include #include namespace tools { @@ -114,4 +115,30 @@ std::string friendly_duration(std::chrono::nanoseconds dur) { return os.str(); } +std::string short_duration(std::chrono::duration dur) { + std::ostringstream os; + os << std::fixed << std::setprecision(1); + if (dur >= 36h) + os << dur / 24h; + else if (dur >= 90min) + os << dur / 1h; + else if (dur >= 90s) + os << dur / 1min; + else if (dur >= 1s) + os << dur / 1s; + else if (dur >= 100ms) + os << std::setprecision(0) << dur / 1ms; + else if (dur >= 1ms) + os << dur / 1ms; + else if (dur >= 100us) + os << std::setprecision(0) << dur / 1us; + else if (dur >= 1us) + os << dur / 1us; + else if (dur >= 1ns) + os << std::setprecision(0) << dur / 1ns; + else + os << "0s"; + return os.str(); +} + } diff --git a/src/common/string_util.h b/src/common/string_util.h index 95b4ea0700c..945989446a9 100755 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -125,9 +125,12 @@ T make_from_guts(std::string_view s) { std::string lowercase_ascii_string(std::string_view src); -/// Converts a duration into a human friendlier string. +/// Converts a duration into a human friendlier string. such as "3d7d47m12s" or "347µs" std::string friendly_duration(std::chrono::nanoseconds dur); +/// Converts a duration into a shorter, single-unit fractional display such as `42.3min` +std::string short_duration(std::chrono::duration dur); + /// Given an array of string arguments, look for strings of the format and return /// Returns empty string view if not found. template From fe50b84774d20302c30da77ddcaea890932d75bf Mon Sep 17 00:00:00 2001 From: victor-tucci Date: Wed, 14 Jun 2023 13:18:33 +0530 Subject: [PATCH 2/3] device: C++ cleanups and modernization --- src/device/device.hpp | 64 +++-- src/device/device_default.cpp | 42 +-- src/device/device_default.hpp | 26 +- src/device/device_ledger.cpp | 268 +++++++++---------- src/device/device_ledger.hpp | 33 +-- src/device/{device_io.hpp => io_device.hpp} | 25 +- src/device/{device_io_hid.cpp => io_hid.cpp} | 209 ++++++--------- src/device/{device_io_hid.hpp => io_hid.hpp} | 51 ++-- src/ringct/rctSigs.cpp | 4 +- src/simplewallet/simplewallet.cpp | 4 +- src/wallet/api/wallet_manager.cpp | 2 +- src/wallet/wallet2.cpp | 64 ++--- src/wallet/wallet2.h | 10 +- 13 files changed, 347 insertions(+), 455 deletions(-) rename src/device/{device_io.hpp => io_device.hpp} (77%) rename src/device/{device_io_hid.cpp => io_hid.cpp} (52%) rename src/device/{device_io_hid.hpp => io_hid.hpp} (70%) diff --git a/src/device/device.hpp b/src/device/device.hpp index 7d89cc796e0..4083d31cc31 100755 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -62,14 +62,6 @@ namespace cryptonote } namespace hw { - namespace { - //device funcion not supported - #define dfns() \ - throw std::runtime_error(std::string("device function not supported: ")+ std::string(__FUNCTION__) + \ - std::string(" (device.hpp line ")+std::to_string(__LINE__)+std::string(").")); \ - return false; - } - class device_progress { public: virtual double progress() const { return 0; } @@ -92,18 +84,22 @@ namespace hw { public: - device(): mode(NONE) {} - device(const device &hwdev) {} - virtual ~device() {} + device() = default; + device(const device&) = delete; + device& operator=(const device&) = delete; + device(device&&) = default; + device& operator=(device&&) = default; + + virtual ~device() = default; - explicit virtual operator bool() const = 0; - enum device_mode { + virtual bool is_hardware_device() const = 0; + enum class mode { NONE, TRANSACTION_CREATE_REAL, TRANSACTION_CREATE_FAKE, TRANSACTION_PARSE }; - enum device_type + enum class type { SOFTWARE = 0, LEDGER = 1, @@ -111,10 +107,10 @@ namespace hw { }; - enum device_protocol_t { - PROTOCOL_DEFAULT, - PROTOCOL_PROXY, // Originally defined by Ledger - PROTOCOL_COLD, // Originally defined by Trezor + enum class protocol { + DEFAULT, + PROXY, // Originally defined by Ledger + COLD, // Originally defined by Trezor }; /* ======================================================================= */ @@ -123,18 +119,18 @@ namespace hw { virtual bool set_name(std::string_view name) = 0; virtual std::string get_name() const = 0; - virtual bool init(void) = 0; + virtual bool init() = 0; virtual bool release() = 0; - virtual bool connect(void) = 0; - virtual bool disconnect(void) = 0; + virtual bool connect() = 0; + virtual bool disconnect() = 0; - virtual bool set_mode(device_mode mode) { this->mode = mode; return true; } - virtual device_mode get_mode() const { return mode; } + virtual bool set_mode(mode m) { mode_ = m; return true; } + virtual mode get_mode() const { return mode_; } - virtual device_type get_type() const = 0; + virtual type get_type() const = 0; - virtual device_protocol_t device_protocol() const { return PROTOCOL_DEFAULT; }; + virtual protocol device_protocol() const { return protocol::DEFAULT; }; virtual void set_callback(i_device_callback * callback) {}; virtual void set_derivation_path(const std::string &derivation_path) {}; @@ -144,9 +140,9 @@ namespace hw { /* ======================================================================= */ /* LOCKER */ /* ======================================================================= */ - virtual void lock(void) = 0; - virtual void unlock(void) = 0; - virtual bool try_lock(void) = 0; + virtual void lock() = 0; + virtual void unlock() = 0; + virtual bool try_lock() = 0; /* ======================================================================= */ @@ -255,24 +251,24 @@ namespace hw { // secret key value, if necessary. virtual bool update_staking_tx_secret_key(crypto::secret_key& key) = 0; - virtual bool close_tx(void) = 0; + virtual bool close_tx() = 0; - virtual bool has_ki_cold_sync(void) const { return false; } - virtual bool has_tx_cold_sign(void) const { return false; } - virtual bool has_ki_live_refresh(void) const { return true; } + virtual bool has_ki_cold_sync() const { return false; } + virtual bool has_tx_cold_sign() const { return false; } + virtual bool has_ki_live_refresh() const { return true; } virtual bool compute_key_image(const cryptonote::account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const cryptonote::subaddress_index& received_index, cryptonote::keypair& in_ephemeral, crypto::key_image& ki) { return false; } virtual void computing_key_images(bool started) {}; virtual void set_network_type(cryptonote::network_type network_type) { } virtual void display_address(const cryptonote::subaddress_index& index, const std::optional &payment_id) {} protected: - device_mode mode; + mode mode_ =mode::NONE; } ; struct mode_resetter { device& hwref; mode_resetter(hw::device& dev) : hwref(dev) { } - ~mode_resetter() { hwref.set_mode(hw::device::NONE);} + ~mode_resetter() { hwref.set_mode(hw::device::mode::NONE);} }; class device_registry { diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index 74f814c6395..ee157bbc612 100755 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -40,17 +40,14 @@ #include "cryptonote_config.h" #include -namespace hw { - - namespace core { - - device_default::device_default() { } - - device_default::~device_default() { } +namespace hw::core { /* ===================================================================== */ /* === Misc ==== */ /* ===================================================================== */ + + // EW, this crap is NASTY. See the comment/TODO in crypto/crypto.cpp (which is where this + // nasty crap was copied from). static inline unsigned char *operator &(crypto::ec_scalar &scalar) { return &reinterpret_cast(scalar); } @@ -61,32 +58,28 @@ namespace hw { /* ======================================================================= */ /* SETUP/TEARDOWN */ /* ======================================================================= */ - bool device_default::set_name(std::string_view name) { - this->name = name; + bool device_default::set_name(std::string_view n) { + name = n; return true; } std::string device_default::get_name() const { return name; } - bool device_default::init(void) { + bool device_default::init() { return true; } bool device_default::release() { return true; } - bool device_default::connect(void) { + bool device_default::connect() { return true; } bool device_default::disconnect() { return true; } - bool device_default::set_mode(device_mode mode) { - return device::set_mode(mode); - } - /* ======================================================================= */ /* LOCKER */ /* ======================================================================= */ @@ -112,10 +105,11 @@ namespace hw { return true; } bool device_default::get_public_address(cryptonote::account_public_address &pubkey) { - dfns(); + throw std::runtime_error{"device function not supported: get_public_address"}; } bool device_default::get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) { - dfns(); + throw std::runtime_error{"device function not supported: get_secret_keys"}; + } /* ======================================================================= */ /* SUB ADDRESS */ @@ -476,17 +470,9 @@ namespace hw { /* ---------------------------------------------------------- */ - static device_default *default_core_device = NULL; void register_all(std::map> ®istry) { - if (!default_core_device) { - default_core_device = new device_default(); - default_core_device->set_name("default_core_device"); - - } - registry.insert(std::make_pair("default", std::unique_ptr(default_core_device))); + auto dev = std::make_unique(); + dev->set_name("default_core_device"); + registry.emplace("default", std::move(dev)); } - - - } - } diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp index e414b4311e8..b949e7a75fe 100755 --- a/src/device/device_default.hpp +++ b/src/device/device_default.hpp @@ -39,36 +39,30 @@ namespace hw { class device_default : public hw::device { public: - device_default(); - ~device_default(); + device_default() = default; - device_default(const device_default &device) = delete; - device_default& operator=(const device_default &device) = delete; + bool is_hardware_device() const override { return false; }; - explicit operator bool() const override { return false; }; - - /* ======================================================================= */ + /* ======================================================================= */ /* SETUP/TEARDOWN */ /* ======================================================================= */ bool set_name(std::string_view name) override; std::string get_name() const override; - bool init(void) override; + bool init() override; bool release() override; - bool connect(void) override; + bool connect() override; bool disconnect() override; - bool set_mode(device_mode mode) override; - - device_type get_type() const override {return device_type::SOFTWARE;}; + type get_type() const override { return type::SOFTWARE; }; /* ======================================================================= */ /* LOCKER */ /* ======================================================================= */ - void lock(void) override; - void unlock(void) override; - bool try_lock(void) override; + void lock() override; + void unlock() override; + bool try_lock() override; /* ======================================================================= */ /* WALLET & ADDRESS */ @@ -152,7 +146,7 @@ namespace hw { bool update_staking_tx_secret_key(crypto::secret_key& key) override; - bool close_tx(void) override; + bool close_tx() override; }; } diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 49a4582a89d..fdc6e1c2d2c 100755 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -28,6 +28,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#include "io_hid.hpp" #include "version.h" #include "device_ledger.hpp" #include "ringct/rctOps.h" @@ -43,9 +44,7 @@ #include #endif -namespace hw { - - namespace ledger { + namespace hw::ledger { #ifdef WITH_DEVICE_LEDGER @@ -125,13 +124,12 @@ namespace hw { } void HMACmap::find_mac(const uint8_t sec[32], uint8_t hmac[32]) { - size_t sz = hmacs.size(); log_hexbuffer("find_mac: lookup for ", sec,32); - for (size_t i=0; i(std::chrono::steady_clock::now() - last_cmd).count() << "ms): " + MDEBUG("RESP (+" << tools::short_duration(std::chrono::steady_clock::now() - last_cmd) << "): " << oxenc::to_hex(std::string_view{reinterpret_cast(&sw), sizeof(sw)}) << ' ' << oxenc::to_hex(buffer_recv, buffer_recv + length_recv)); } @@ -488,12 +484,11 @@ namespace hw { CHECK_AND_ASSERT_THROW_MES(length_recv>=3, "Communication error, less than three bytes received. Check your application version."); - unsigned int device_version = 0; - device_version = VERSION(buffer_recv[0], buffer_recv[1], buffer_recv[2]); + std::array device_version = {buffer_recv[0], buffer_recv[1], buffer_recv[2]}; - CHECK_AND_ASSERT_THROW_MES (device_version >= MINIMAL_APP_VERSION, - "Unsupported device application version: " << VERSION_MAJOR(device_version)<<"."<= MINIMUM_APP_VERSION, + "Unsupported device application version: " << tools::join(".", device_version) << + " At least " << tools::join(".", MINIMUM_APP_VERSION) <<" is required."); return true; } @@ -549,8 +544,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int /* SETUP/TEARDOWN */ /* ======================================================================= */ - bool device_ledger::set_name(std::string_view name) { - this->name = name; + bool device_ledger::set_name(std::string_view n) { + name = n; return true; } @@ -562,7 +557,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int bool device_ledger::init() { #ifdef DEBUG_HWDEVICE - debug_device = &hw::get_device("default"); + debug_device = &get_device("default"); #endif release(); hw_device.init(); @@ -570,7 +565,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int return true; } - static const std::vector known_devices { + static const std::vector known_devices { {0x2c97, 0x0001, 0, 0xffa0}, {0x2c97, 0x0004, 0, 0xffa0}, }; @@ -637,31 +632,25 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int nettype = set_nettype; } - bool device_ledger::set_mode(device_mode mode) { - auto locks = tools::unique_locks(device_locker, command_locker); - - int offset; - - switch(mode) { - case TRANSACTION_CREATE_REAL: - case TRANSACTION_CREATE_FAKE: - offset = set_command_header_noopt(INS_SET_SIGNATURE_MODE, 1); - buffer_send[offset++] = mode; - - finish_and_exchange(offset); + bool device_ledger::set_mode(mode m) { + auto locks = tools::unique_locks(device_locker, command_locker); - this->mode = mode; - break; + switch(m) { + case mode::TRANSACTION_CREATE_REAL: + case mode::TRANSACTION_CREATE_FAKE: + { + offset = set_command_header_noopt(INS_SET_SIGNATURE_MODE, 1); + buffer_send[offset++] = static_cast(m); - 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: "<(m)); + return device::set_mode(m); } @@ -711,7 +700,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int #ifdef DEBUG_HWDEVICE crypto::chacha_key key_x; - debug_device->generate_chacha_key(hw::ledger::decrypt(keys), key_x, kdf_rounds); + debug_device->generate_chacha_key(decrypt(keys), key_x, kdf_rounds); #endif send_simple(INS_GET_CHACHA8_PREKEY); @@ -721,7 +710,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int crypto::generate_chacha_key_prehashed(prekey, sizeof(prekey), key, kdf_rounds); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("generate_chacha_key_prehashed", "key", key_x.data(), key.data()); + check32("generate_chacha_key_prehashed", "key", key_x.data(), key.data()); #endif return true; @@ -749,7 +738,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int #ifdef DEBUG_HWDEVICE crypto::key_derivation derivation_x = - (mode == TRANSACTION_PARSE && has_view_key) ? derivation : hw::ledger::decrypt(derivation); + (mode_ == mode::TRANSACTION_PARSE && has_view_key) ? derivation : decrypt(derivation); log_hexbuffer("derive_subaddress_public_key: [[IN]] pub ", pub.data, 32); log_hexbuffer("derive_subaddress_public_key: [[IN]] derivation", derivation_x.data, 32); log_message( "derive_subaddress_public_key: [[IN]] index ", std::to_string(output_index)); @@ -758,7 +747,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32); #endif - if (mode == TRANSACTION_PARSE && has_view_key) { + if (mode_ == 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"); @@ -779,7 +768,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(derived_pub.data, 32); } #ifdef DEBUG_HWDEVICE - hw::ledger::check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); + check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); #endif return true; @@ -790,7 +779,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int crypto::public_key D; #ifdef DEBUG_HWDEVICE - const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); + const cryptonote::account_keys keys_x = decrypt(keys); log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_spend_secret_key", keys_x.m_spend_secret_key.data, 32); log_message ("get_subaddress_spend_public_key: [[IN]] index ", std::to_string(index.major)+"."+std::to_string(index.minor)); @@ -813,7 +802,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int } #ifdef DEBUG_HWDEVICE - hw::ledger::check32("get_subaddress_spend_public_key", "D", D_x.data, D.data); + check32("get_subaddress_spend_public_key", "D", D_x.data, D.data); #endif return D; @@ -834,7 +823,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int cryptonote::account_public_address address; #ifdef DEBUG_HWDEVICE - const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); + const cryptonote::account_keys keys_x = decrypt(keys); log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); log_hexbuffer("get_subaddress: [[IN]] keys.m_view_public_key", keys_x.m_account_address.m_view_public_key.data, 32); log_hexbuffer("get_subaddress: [[IN]] keys.m_spend_secret_key ", keys_x.m_spend_secret_key.data, 32); @@ -861,8 +850,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int } #ifdef DEBUG_HWDEVICE - hw::ledger::check32("get_subaddress", "address.m_view_public_key.data", address_x.m_view_public_key.data, address.m_view_public_key.data); - hw::ledger::check32("get_subaddress", "address.m_spend_public_key.data", address_x.m_spend_public_key.data, address.m_spend_public_key.data); + check32("get_subaddress", "address.m_view_public_key.data", address_x.m_view_public_key.data, address.m_view_public_key.data); + check32("get_subaddress", "address.m_spend_public_key.data", address_x.m_spend_public_key.data, address.m_spend_public_key.data); #endif return address; @@ -873,7 +862,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int crypto::secret_key sub_sec; #ifdef DEBUG_HWDEVICE - const crypto::secret_key sec_x = hw::ledger::decrypt(sec); + const crypto::secret_key sec_x = decrypt(sec); log_message ("get_subaddress_secret_key: [[IN]] index ", std::to_string(index.major)+"."+std::to_string(index.minor)); log_hexbuffer("get_subaddress_secret_key: [[IN]] sec ", sec_x.data, 32); crypto::secret_key sub_sec_x = debug_device->get_subaddress_secret_key(sec_x, index); @@ -893,8 +882,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_secret(sub_sec.data, offset); #ifdef DEBUG_HWDEVICE - crypto::secret_key sub_sec_clear = hw::ledger::decrypt(sub_sec); - hw::ledger::check32("get_subaddress_secret_key", "sub_sec", sub_sec_x.data, sub_sec_clear.data); + crypto::secret_key sub_sec_clear = decrypt(sub_sec); + check32("get_subaddress_secret_key", "sub_sec", sub_sec_x.data, sub_sec_clear.data); #endif return sub_sec; @@ -926,7 +915,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - const rct::key a_x = hw::ledger::decrypt(a); + const rct::key a_x = decrypt(a); log_hexbuffer("scalarmultKey: [[IN]] P ", P.bytes, 32); log_hexbuffer("scalarmultKey: [[IN]] a ", a_x.bytes, 32); rct::key aP_x; @@ -946,7 +935,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(aP.bytes, 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("scalarmultKey", "mulkey", aP_x.bytes, aP.bytes); + check32("scalarmultKey", "mulkey", aP_x.bytes, aP.bytes); #endif return true; @@ -956,7 +945,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - const rct::key a_x = hw::ledger::decrypt(a); + const rct::key a_x = decrypt(a); log_hexbuffer("scalarmultKey: [[IN]] a ", a_x.bytes, 32); rct::key aG_x; debug_device->scalarmultBase(aG_x, a_x); @@ -973,7 +962,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(aG.bytes, 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("scalarmultBase", "mulkey", aG_x.bytes, aG.bytes); + check32("scalarmultBase", "mulkey", aG_x.bytes, aG.bytes); #endif return true; @@ -984,8 +973,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int int offset; #ifdef DEBUG_HWDEVICE - const crypto::secret_key a_x = hw::ledger::decrypt(a); - const crypto::secret_key b_x = hw::ledger::decrypt(b); + const crypto::secret_key a_x = decrypt(a); + const crypto::secret_key b_x = decrypt(b); log_hexbuffer("sc_secret_add: [[IN]] a ", a_x.data, 32); log_hexbuffer("sc_secret_add: [[IN]] b ", b_x.data, 32); crypto::secret_key r_x; @@ -1007,8 +996,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_secret(r.data, offset); #ifdef DEBUG_HWDEVICE - crypto::secret_key r_clear = hw::ledger::decrypt(r); - hw::ledger::check32("sc_secret_add", "r", r_x.data, r_clear.data); + crypto::secret_key r_clear = decrypt(r); + check32("sc_secret_add", "r", r_x.data, r_clear.data); #endif return true; @@ -1026,7 +1015,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int crypto::secret_key sec_x; crypto::secret_key recovery_key_x; if (recover) { - recovery_key_x = hw::ledger::decrypt(recovery_key); + recovery_key_x = decrypt(recovery_key); log_hexbuffer("generate_keys: [[IN]] pub", recovery_key_x.data, 32); } #endif @@ -1039,13 +1028,13 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_secret(sec.data, offset); #ifdef DEBUG_HWDEVICE - crypto::secret_key sec_clear = hw::ledger::decrypt(sec); + crypto::secret_key sec_clear = decrypt(sec); sec_x = sec_clear; log_hexbuffer("generate_keys: [[OUT]] pub", pub.data, 32); log_hexbuffer("generate_keys: [[OUT]] sec", sec_clear.data, 32); crypto::secret_key_to_public_key(sec_x,pub_x); - hw::ledger::check32("generate_keys", "pub", pub_x.data, pub.data); + check32("generate_keys", "pub", pub_x.data, pub.data); #endif return sec; @@ -1058,14 +1047,14 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int #ifdef DEBUG_HWDEVICE log_hexbuffer("generate_key_derivation: [[IN]] pub ", pub.data, 32); - const crypto::secret_key sec_x = (sec == rct::rct2sk(rct::I)) ? sec : hw::ledger::decrypt(sec); + const crypto::secret_key sec_x = (sec == rct::rct2sk(rct::I)) ? sec : decrypt(sec); log_hexbuffer("generate_key_derivation: [[IN]] sec ", sec_x.data, 32); crypto::key_derivation derivation_x; debug_device->generate_key_derivation(pub, sec_x, derivation_x); log_hexbuffer("generate_key_derivation: [[OUT]] derivation", derivation_x.data, 32); #endif - if (mode == TRANSACTION_PARSE && has_view_key) { + if (mode_ == mode::TRANSACTION_PARSE && has_view_key) { //A derivation is requested in PARSE mode and we have the view key, //so do that without the device and return the derivation unencrypted. MDEBUG( "generate_key_derivation : PARSE mode with known viewkey"); @@ -1089,8 +1078,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int } #ifdef DEBUG_HWDEVICE crypto::key_derivation derivation_clear = - (mode == TRANSACTION_PARSE && has_view_key) ? derivation : hw::ledger::decrypt(derivation); - hw::ledger::check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data); + (mode_ == mode::TRANSACTION_PARSE && has_view_key) ? derivation : decrypt(derivation); + check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data); #endif return r; @@ -1118,7 +1107,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); + const crypto::key_derivation derivation_x = decrypt(derivation); log_hexbuffer("derivation_to_scalar: [[IN]] derivation ", derivation_x.data, 32); log_message ("derivation_to_scalar: [[IN]] output_index ", std::to_string(output_index)); crypto::ec_scalar res_x; @@ -1140,8 +1129,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_secret(res.data, offset); #ifdef DEBUG_HWDEVICE - crypto::ec_scalar res_clear = hw::ledger::decrypt(res); - hw::ledger::check32("derivation_to_scalar", "res", res_x.data, res_clear.data); + crypto::ec_scalar res_clear = decrypt(res); + check32("derivation_to_scalar", "res", res_x.data, res_clear.data); #endif return true; @@ -1151,8 +1140,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); - const crypto::secret_key sec_x = hw::ledger::decrypt(sec); + const crypto::key_derivation derivation_x = decrypt(derivation); + const crypto::secret_key sec_x = decrypt(sec); log_hexbuffer("derive_secret_key: [[IN]] derivation ", derivation_x.data, 32); log_message ("derive_secret_key: [[IN]] index ", std::to_string(output_index)); log_hexbuffer("derive_secret_key: [[IN]] sec ", sec_x.data, 32); @@ -1176,8 +1165,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_secret(derived_sec.data, offset); #ifdef DEBUG_HWDEVICE - crypto::secret_key derived_sec_clear = hw::ledger::decrypt(derived_sec); - hw::ledger::check32("derive_secret_key", "derived_sec", derived_sec_x.data, derived_sec_clear.data); + crypto::secret_key derived_sec_clear = decrypt(derived_sec); + check32("derive_secret_key", "derived_sec", derived_sec_x.data, derived_sec_clear.data); #endif return true; @@ -1187,7 +1176,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); + const crypto::key_derivation derivation_x = decrypt(derivation); log_hexbuffer("derive_public_key: [[IN]] derivation ", derivation_x.data, 32); log_message ("derive_public_key: [[IN]] output_index", std::to_string(output_index)); log_hexbuffer("derive_public_key: [[IN]] pub ", pub.data, 32); @@ -1210,7 +1199,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(derived_pub.data, 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("derive_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); + check32("derive_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); #endif return true; @@ -1220,7 +1209,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - const crypto::secret_key sec_x = hw::ledger::decrypt(sec); + const crypto::secret_key sec_x = decrypt(sec); log_hexbuffer("secret_key_to_public_key: [[IN]] sec ", sec_x.data, 32); crypto::public_key pub_x; bool rc = debug_device->secret_key_to_public_key(sec_x, pub_x); @@ -1240,7 +1229,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(pub.data, 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("secret_key_to_public_key", "pub", pub_x.data, pub.data); + check32("secret_key_to_public_key", "pub", pub_x.data, pub.data); #endif return true; @@ -1250,7 +1239,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - const crypto::secret_key sec_x = hw::ledger::decrypt(sec); + const crypto::secret_key sec_x = decrypt(sec); log_hexbuffer("generate_key_image: [[IN]] pub ", pub.data, 32); log_hexbuffer("generate_key_image: [[IN]] sec ", sec_x.data, 32); crypto::key_image image_x; @@ -1270,7 +1259,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(image.data, 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("generate_key_image", "image", image_x.data, image.data); + check32("generate_key_image", "image", image_x.data, image.data); #endif return true; @@ -1307,7 +1296,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int #ifdef DEBUG_HWDEVICE log_hexbuffer("generate_unlock_signature: [[IN]] pub ", pub.data, 32); - const crypto::secret_key sec_x = hw::ledger::decrypt(sec); + const crypto::secret_key sec_x = decrypt(sec); log_hexbuffer("generate_unlock_signature: [[IN]] sec ", sec_x.data, 32); #endif @@ -1369,7 +1358,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int const crypto::public_key A_x = A; const std::optional B_x = B; const crypto::public_key D_x = D; - const crypto::secret_key r_x = hw::ledger::decrypt(r); + const crypto::secret_key r_x = decrypt(r); crypto::signature sig_x; log_hexbuffer("generate_tx_proof: [[IN]] prefix_hash ", prefix_hash_x.data, 32); log_hexbuffer("generate_tx_proof: [[IN]] R ", R_x.data, 32); @@ -1402,8 +1391,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int debug_device->generate_tx_proof(prefix_hash_x, R_x, A_x, B_x, D_x, r_x, sig_x); MDEBUG("FAIL is normal if random is not fixed in proof"); - hw::ledger::check32("generate_tx_proof", "c", sig_x.c.data, sig.c.data); - hw::ledger::check32("generate_tx_proof", "r", sig_x.r.data, sig.r.data); + check32("generate_tx_proof", "c", sig_x.c.data, sig.c.data); + check32("generate_tx_proof", "r", sig_x.r.data, sig.r.data); #endif } @@ -1429,7 +1418,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_secret(tmp, offset); #ifdef DEBUG_HWDEVICE - const crypto::secret_key r_x = hw::ledger::decrypt(tx_key); + const crypto::secret_key r_x = decrypt(tx_key); log_hexbuffer("open_tx: [[OUT]] R ", buffer_recv, 32); log_hexbuffer("open_tx: [[OUT]] r ", r_x.data, 32); #endif @@ -1505,7 +1494,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(h.data, 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check8("prefix_hash", "h", h_x.data, h.data); + check8("prefix_hash", "h", h_x.data, h.data); #endif } @@ -1513,7 +1502,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - const crypto::secret_key secret_key_x = hw::ledger::decrypt(secret_key); + const crypto::secret_key secret_key_x = decrypt(secret_key); log_hexbuffer("encrypt_payment_id: [[IN]] payment_id ", payment_id.data, 32); log_hexbuffer("encrypt_payment_id: [[IN]] public_key ", public_key.data, 32); log_hexbuffer("encrypt_payment_id: [[IN]] secret_key ", secret_key_x.data, 32); @@ -1531,7 +1520,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(payment_id.data, 8); #ifdef DEBUG_HWDEVICE - hw::ledger::check8("stealth", "payment_id", payment_id_x.data, payment_id.data); + check8("stealth", "payment_id", payment_id_x.data, payment_id.data); #endif return true; @@ -1556,14 +1545,14 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - cryptonote::account_keys sender_account_keys_x = hw::ledger::decrypt(sender_account_keys); + cryptonote::account_keys sender_account_keys_x = decrypt(sender_account_keys); std::memmove(sender_account_keys_x.m_view_secret_key.data, dbg_viewkey.data, 32); - const crypto::secret_key tx_key_x = hw::ledger::decrypt(tx_key); + const crypto::secret_key tx_key_x = decrypt(tx_key); std::vector additional_tx_keys_x; for (const auto& k: additional_tx_keys) { - additional_tx_keys_x.push_back(hw::ledger::decrypt(k)); + additional_tx_keys_x.push_back(decrypt(k)); } log_message("generate_output_ephemeral_keys: [[IN]] tx_version", std::to_string(tx_version)); @@ -1652,13 +1641,13 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int amount_keys.back(), out_eph_public_key); #ifdef DEBUG_HWDEVICE - rct::key amount_back = hw::ledger::decrypt(amount_keys.back()); + rct::key amount_back = decrypt(amount_keys.back()); log_hexbuffer("generate_output_ephemeral_keys: clear amount_key", amount_back.bytes, 32); - hw::ledger::check32("generate_output_ephemeral_keys", "amount_key", amount_keys_x.back().bytes, amount_back.bytes); + check32("generate_output_ephemeral_keys", "amount_key", amount_keys_x.back().bytes, amount_back.bytes); if (need_additional_txkeys) { - hw::ledger::check32("generate_output_ephemeral_keys", "additional_tx_key", additional_tx_public_keys_x.back().data, additional_tx_public_keys.back().data); + check32("generate_output_ephemeral_keys", "additional_tx_key", additional_tx_public_keys_x.back().data, additional_tx_public_keys.back().data); } - hw::ledger::check32("generate_output_ephemeral_keys", "out_eph_public_key", out_eph_public_key_x.data, out_eph_public_key.data); + check32("generate_output_ephemeral_keys", "out_eph_public_key", out_eph_public_key_x.data, out_eph_public_key.data); #endif return true; @@ -1673,7 +1662,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int rct::key device_ledger::genCommitmentMask(const rct::key &AKout) { #ifdef DEBUG_HWDEVICE - rct::key mask_x = debug_device->genCommitmentMask(hw::ledger::decrypt(AKout)); + rct::key mask_x = debug_device->genCommitmentMask(decrypt(AKout)); #endif rct::key mask; @@ -1686,7 +1675,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(mask.bytes, 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("genCommitmentMask", "mask", mask_x.bytes, mask.bytes); + check32("genCommitmentMask", "mask", mask_x.bytes, mask.bytes); #endif return mask; @@ -1696,7 +1685,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - const rct::key AKout_x = hw::ledger::decrypt(AKout); + const rct::key AKout_x = decrypt(AKout); rct::ecdhTuple unmasked_x = unmasked; debug_device->ecdhEncode(unmasked_x, AKout_x, short_amount); #endif @@ -1715,8 +1704,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int #ifdef DEBUG_HWDEVICE MDEBUG("ecdhEncode: Akout: "<ecdhDecode(masked_x, AKout_x, short_amount); #endif @@ -1747,8 +1736,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int #ifdef DEBUG_HWDEVICE MDEBUG("ecdhEncode: Akout: "<buffer_recv, 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("mlsag_prehash", "prehash", (char*)prehash_x.bytes, (char*)prehash.bytes); + check32("mlsag_prehash", "prehash", (char*)prehash_x.bytes, (char*)prehash.bytes); #endif return true; @@ -1937,7 +1926,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int #ifdef DEBUG_HWDEVICE const rct::key H_x = H; - const rct::key xx_x = hw::ledger::decrypt(xx); + const rct::key xx_x = decrypt(xx); rct::key a_x; rct::key aG_x; rct::key aHP_x; @@ -1964,14 +1953,14 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int memmove(II.bytes, &this->buffer_recv[offset], 32); #ifdef DEBUG_HWDEVICE - a_x = hw::ledger::decrypt(a); + a_x = decrypt(a); rct::scalarmultBase(aG_x, a_x); rct::scalarmultKey(aHP_x, H_x, a_x); rct::scalarmultKey(II_x, H_x, xx_x); - hw::ledger::check32("mlsag_prepare", "AG", (char*)aG_x.bytes, (char*)aG.bytes); - hw::ledger::check32("mlsag_prepare", "aHP", (char*)aHP_x.bytes, (char*)aHP.bytes); - hw::ledger::check32("mlsag_prepare", "II", (char*)II_x.bytes, (char*)II.bytes); + check32("mlsag_prepare", "AG", (char*)aG_x.bytes, (char*)aG.bytes); + check32("mlsag_prepare", "aHP", (char*)aHP_x.bytes, (char*)aHP.bytes); + check32("mlsag_prepare", "II", (char*)II_x.bytes, (char*)II.bytes); #endif return true; @@ -1993,9 +1982,9 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int memmove(aG.bytes, &this->buffer_recv[offset], 32); #ifdef DEBUG_HWDEVICE - a_x = hw::ledger::decrypt(a); + a_x = decrypt(a); rct::scalarmultBase(aG_x, a_x); - hw::ledger::check32("mlsag_prepare", "AG", (char*)aG_x.bytes, (char*)aG.bytes); + check32("mlsag_prepare", "AG", (char*)aG_x.bytes, (char*)aG.bytes); #endif return true; @@ -2030,7 +2019,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int memmove(c.bytes, &this->buffer_recv[0], 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("mlsag_hash", "c", (char*)c_x.bytes, (char*)c.bytes); + check32("mlsag_hash", "c", (char*)c_x.bytes, (char*)c.bytes); #endif return true; @@ -2046,8 +2035,8 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int #ifdef DEBUG_HWDEVICE const rct::key c_x = c; - const rct::keyV xx_x = hw::ledger::decrypt(xx); - const rct::keyV alpha_x = hw::ledger::decrypt(alpha); + const rct::keyV xx_x = decrypt(xx); + const rct::keyV alpha_x = decrypt(alpha); const int rows_x = rows; const int dsRows_x = dsRows; rct::keyV ss_x(ss.size()); @@ -2081,7 +2070,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int #ifdef DEBUG_HWDEVICE for (size_t j = 0; j < rows; j++) { - hw::ledger::check32("mlsag_sign", "ss["+std::to_string(j)+"]", (char*)ss_x[j].bytes, (char*)ss[j].bytes); + check32("mlsag_sign", "ss["+std::to_string(j)+"]", (char*)ss_x[j].bytes, (char*)ss[j].bytes); } #endif @@ -2176,7 +2165,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(prehash.bytes, 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("clsag_prehash", "prehash", prehash_x.bytes, prehash.bytes); + check32("clsag_prehash", "prehash", prehash_x.bytes, prehash.bytes); #endif return true; @@ -2185,7 +2174,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int bool device_ledger::clsag_prepare(const rct::key &p, const rct::key &z, rct::key &I, rct::key &D, const rct::key &H, rct::key &a, rct::key &aG, rct::key &aH) { auto locks = tools::unique_locks(device_locker, command_locker); #ifdef DEBUG_HWDEVICE - const rct::key p_x = hw::ledger::decrypt(p); + const rct::key p_x = decrypt(p); rct::key I_x; rct::key D_x; rct::key a_x; @@ -2215,11 +2204,11 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(D.bytes, 32, offset); //D = zH #ifdef DEBUG_HWDEVICE - hw::ledger::check32("clsag_prepare", "I", I_x.bytes, I.bytes); - hw::ledger::check32("clsag_prepare", "D", D_x.bytes, D.bytes); - hw::ledger::check32("clsag_prepare", "a", a_x.bytes, a.bytes); - hw::ledger::check32("clsag_prepare", "aG", aG_x.bytes, aG.bytes); - hw::ledger::check32("clsag_prepare", "aH", aH_x.bytes, aH.bytes); + check32("clsag_prepare", "I", I_x.bytes, I.bytes); + check32("clsag_prepare", "D", D_x.bytes, D.bytes); + check32("clsag_prepare", "a", a_x.bytes, a.bytes); + check32("clsag_prepare", "aG", aG_x.bytes, aG.bytes); + check32("clsag_prepare", "aH", aH_x.bytes, aH.bytes); #endif return true; @@ -2240,7 +2229,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(hash.bytes, 32); #ifdef DEBUG_HWDEVICE - hw::ledger::check32("clsag_hash", "hash", hash_x.bytes, hash.bytes); + check32("clsag_hash", "hash", hash_x.bytes, hash.bytes); #endif return true; } @@ -2250,7 +2239,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int #ifdef DEBUG_HWDEVICE rct::key s_x; - debug_device->clsag_sign(c, hw::ledger::decrypt(a), hw::ledger::decrypt(p), z, mu_P, mu_C, s_x); + debug_device->clsag_sign(c, decrypt(a), decrypt(p), z, mu_P, mu_C, s_x); #endif /* @@ -2274,7 +2263,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int receive_bytes(s.bytes, 32); //s #ifdef DEBUG_HWDEVICE - hw::ledger::check32("clsag_sign", "s", s_x.bytes, s.bytes); + check32("clsag_sign", "s", s_x.bytes, s.bytes); #endif return true; @@ -2303,22 +2292,15 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int /* ---------------------------------------------------------- */ - static device_ledger *legder_device = NULL; - void register_all(std::map> ®istry) { - if (!legder_device) { - legder_device = new device_ledger(); - legder_device->set_name("Ledger"); - } - registry.insert(std::make_pair("Ledger", std::unique_ptr(legder_device))); + void register_all(std::map>& registry) { + registry.emplace("Ledger", std::make_unique()); } #else //WITH_DEVICE_LEDGER - void register_all(std::map> ®istry) { - } + void register_all(std::map> &) {} #endif //WITH_DEVICE_LEDGER - } } diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index 511a7784e9e..68dc0cabb90 100755 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -35,28 +35,17 @@ #include #include "device.hpp" #include "log.hpp" -#include "device_io_hid.hpp" +#include "io_hid.hpp" -namespace hw { +namespace hw::ledger { using namespace std::literals; - namespace ledger { - // Required coin value as returned by INS_GET_NETWORK during connection constexpr auto COIN_NETWORK = "BELDEX"sv; /* Minimal supported version */ - #define MINIMAL_APP_VERSION_MAJOR 0 - #define MINIMAL_APP_VERSION_MINOR 9 - #define MINIMAL_APP_VERSION_MICRO 0 - - #define VERSION(M,m,u) ((M)<<16|(m)<<8|(u)) - #define VERSION_MAJOR(v) (((v)>>16)&0xFF) - #define VERSION_MINOR(v) (((v)>>8)&0xFF) - #define VERSION_MICRO(v) (((v)>>0)&0xFF) - - #define MINIMAL_APP_VERSION VERSION(MINIMAL_APP_VERSION_MAJOR, MINIMAL_APP_VERSION_MINOR, MINIMAL_APP_VERSION_MICRO) + constexpr std::array MINIMUM_APP_VERSION{0,9,0}; void register_all(std::map> ®istry); @@ -146,14 +135,14 @@ namespace hw { #define BUFFER_SEND_SIZE 262 #define BUFFER_RECV_SIZE 262 - class device_ledger : public hw::device { + class device_ledger : public device { private: // Locker for concurrent access mutable std::recursive_mutex device_locker; mutable std::mutex command_locker; //IO - hw::io::device_io_hid hw_device; + hw::io::hid hw_device; unsigned int length_send; unsigned char buffer_send[BUFFER_SEND_SIZE]; unsigned int length_recv; @@ -186,8 +175,6 @@ namespace hw { void send_finish(int& offset); unsigned int finish_and_exchange(int& offset, bool wait_on_input = false); - // hw running mode - device_mode mode; bool tx_in_progress; cryptonote::network_type nettype = cryptonote::network_type::UNDEFINED; // Set by the wallet before connecting @@ -222,7 +209,7 @@ namespace hw { device_ledger(const device_ledger &device) = delete ; device_ledger& operator=(const device_ledger &device) = delete; - explicit operator bool() const override {return this->connected(); } + bool is_hardware_device() const override {return connected(); } bool reset(); @@ -238,10 +225,10 @@ namespace hw { bool disconnect() override; bool connected() const; - bool set_mode(device_mode mode) override; + bool set_mode(mode m) override; - device_type get_type() const override {return device_type::LEDGER;}; - device_protocol_t device_protocol() const override { return PROTOCOL_PROXY; }; + type get_type() const override {return type::LEDGER;}; + protocol device_protocol() const override { return protocol::PROXY; }; /* ======================================================================= */ /* LOCKER */ @@ -337,7 +324,5 @@ namespace hw { }; #endif //WITH_DEVICE_LEDGER - } } - diff --git a/src/device/device_io.hpp b/src/device/io_device.hpp similarity index 77% rename from src/device/device_io.hpp rename to src/device/io_device.hpp index fe66736f746..4589b8dca68 100755 --- a/src/device/device_io.hpp +++ b/src/device/io_device.hpp @@ -33,24 +33,21 @@ #pragma once -namespace hw { - namespace io { +namespace hw::io { - class device_io { + class device { - public: + public: - device_io() {}; - ~device_io() {}; + virtual ~device() = default; - virtual void init() = 0; - virtual void release() = 0; + virtual void init() = 0; + virtual void release() = 0; - virtual void connect(void *parms) = 0; - virtual void disconnect() = 0; - virtual bool connected() const = 0; + virtual void disconnect() = 0; + virtual bool connected() const = 0; - virtual int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) = 0; - }; + virtual int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) = 0; }; -}; + +} diff --git a/src/device/device_io_hid.cpp b/src/device/io_hid.cpp similarity index 52% rename from src/device/device_io_hid.cpp rename to src/device/io_hid.cpp index cbb34d48b1c..8f712aacc25 100755 --- a/src/device/device_io_hid.cpp +++ b/src/device/io_hid.cpp @@ -30,18 +30,15 @@ #include "common/beldex.h" #include "log.hpp" -#include "device_io_hid.hpp" +#include "io_hid.hpp" + +namespace hw::io { -namespace hw { - namespace io { - #undef BELDEX_DEFAULT_LOG_CATEGORY #define BELDEX_DEFAULT_LOG_CATEGORY "device.io" - #define ASSERT_X(exp,msg) CHECK_AND_ASSERT_THROW_MES(exp, msg); + static constexpr size_t MAX_BLOCK = 64; - #define MAX_BLOCK 64 - static std::string safe_hid_error(hid_device *hwdev) { if (hwdev) { const wchar_t* error_wstr = hid_error(hwdev); @@ -59,57 +56,39 @@ namespace hw { std::wcsrtombs(&error_str[0], &error_wstr, error_str.size(), &state); return error_str; } - return std::string("NULL device"); + return "NULL device"; } static std::string safe_hid_path(const hid_device_info *hwdev_info) { if (hwdev_info && hwdev_info->path) { - return std::string(hwdev_info->path); + return hwdev_info->path; } - return std::string("NULL path"); + return "NULL path"; } - device_io_hid::device_io_hid(unsigned short c, unsigned char t, unsigned int ps, unsigned int to) : - channel(c), - tag(t), - packet_size(ps), - timeout(to), - usb_vid(0), - usb_pid(0), - usb_device(nullptr) { - } - - device_io_hid::device_io_hid() : device_io_hid(DEFAULT_CHANNEL, DEFAULT_TAG, DEFAULT_PACKET_SIZE, DEFAULT_TIMEOUT) { - } + hid::hid(unsigned short c, unsigned char t, unsigned int ps, unsigned int to) + : channel{c}, tag{t}, packet_size{ps}, timeout{to} + {} - void device_io_hid::io_hid_log(int read, unsigned char* buffer, int block_len) { + void hid::io_hid_log(int read, unsigned char* buffer, int block_len) { if (hid_verbose) MDEBUG("HID " << (read ? '<' : '>') << " : " << oxenc::to_hex(buffer, buffer + block_len)); } - void device_io_hid::init() { + void hid::init() { int r; r = hid_init(); - ASSERT_X(r>=0, "Unable to init hidapi library. Error "+std::to_string(r)+": "+safe_hid_error(this->usb_device)); + CHECK_AND_ASSERT_THROW_MES(r>=0, "Unable to init hidapi library. Error "+std::to_string(r)+": "+safe_hid_error(usb_device)); } - void device_io_hid::connect(void *params) { - hid_conn_params *p = (struct hid_conn_params*)params; - if (!this->connect(p->vid, p->pid, p->interface_number, p->usage_page)) { - ASSERT_X(false, "No device found. (Is the device running with the wallet app opened?)"); - } - } - - void device_io_hid::connect(const std::vector &hcpV) { - for (auto p: hcpV) { - if (this->connect(p.vid, p.pid, p.interface_number, p.usage_page)) { + void hid::connect(const std::vector& hcp) { + for (const auto& p : hcp) + if (connect(p.vid, p.pid, p.interface_number, p.usage_page)) return; - } - } - ASSERT_X(false, "No device found. (Is the device running with the wallet app opened?)"); + CHECK_AND_ASSERT_THROW_MES(false, "No device found. (Is the device running with the wallet app opened?)"); } - hid_device_info *device_io_hid::find_device(hid_device_info *devices_list, std::optional interface_number, std::optional usage_page) { + hid_device_info *hid::find_device(hid_device_info *devices_list, std::optional interface_number, std::optional usage_page) { bool select_any = !interface_number && !usage_page; MDEBUG( "Looking for " << @@ -118,61 +97,48 @@ namespace hw { ((interface_number && usage_page) ? " or" : "") << (usage_page ? (" usage_page " + std::to_string(*usage_page)) : "")); - hid_device_info *result = nullptr; - for (; devices_list != nullptr; devices_list = devices_list->next) { - BELDEX_DEFER { - MDEBUG( (result == devices_list ? "SELECTED" : "SKIPPED ") << - " HID Device" << - " path " << safe_hid_path(devices_list) << - " interface_number " << devices_list->interface_number << - " usage_page " << devices_list->usage_page); - }; - - if (result != nullptr) { - continue; - } - - if (select_any) { - result = devices_list; - } else if (interface_number && devices_list->interface_number == *interface_number) { - result = devices_list; - } else if (usage_page && devices_list->usage_page == *usage_page) { + hid_device_info* result = nullptr; + for (; !result && devices_list; devices_list = devices_list->next) { + if (select_any + || (interface_number && devices_list->interface_number == *interface_number) + || (usage_page && devices_list->usage_page == *usage_page)) result = devices_list; - } } - + MDEBUG( (result == devices_list ? "SELECTED" : "SKIPPED ") << + " HID Device" << + " path " << safe_hid_path(devices_list) << + " interface_number " << devices_list->interface_number << + " usage_page " << devices_list->usage_page); return result; } - hid_device *device_io_hid::connect(unsigned int vid, unsigned int pid, std::optional interface_number, std::optional usage_page) { - hid_device_info *hwdev_info_list; - hid_device *hwdev; + bool hid::connect(unsigned int vid, unsigned int pid, std::optional interface_number, std::optional usage_page) { - this->disconnect(); + disconnect(); - hwdev_info_list = hid_enumerate(vid, pid); + hid_device_info* hwdev_info_list = hid_enumerate(vid, pid); if (!hwdev_info_list) { - MDEBUG("Unable to enumerate device "+std::to_string(vid)+":"+std::to_string(vid)+ ": "+ safe_hid_error(this->usb_device)); - return nullptr; + MDEBUG("Unable to enumerate device " << vid << ":" << pid << ": " << safe_hid_error(usb_device)); + return false; } - hwdev = nullptr; + hid_device* hwdev = nullptr; if (hid_device_info *device = find_device(hwdev_info_list, interface_number, usage_page)) { hwdev = hid_open_path(device->path); } hid_free_enumeration(hwdev_info_list); - ASSERT_X(hwdev, "Unable to open device "+std::to_string(pid)+":"+std::to_string(vid)); - this->usb_vid = vid; - this->usb_pid = pid; - this->usb_device = hwdev; + CHECK_AND_ASSERT_THROW_MES(hwdev, "Unable to open device "+std::to_string(pid)+":"+std::to_string(vid)); + usb_vid = vid; + usb_pid = pid; + usb_device = hwdev; return hwdev; } - bool device_io_hid::connected() const { - return this->usb_device != nullptr; + bool hid::connected() const { + return usb_device != nullptr; } - int device_io_hid::exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) { + int hid::exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) { unsigned char buffer[400]; unsigned char padding_buffer[MAX_BLOCK+1]; unsigned int result; @@ -181,11 +147,11 @@ namespace hw { unsigned int remaining; unsigned int offset = 0; - ASSERT_X(this->usb_device,"No device opened"); + CHECK_AND_ASSERT_THROW_MES(usb_device,"No device opened"); //Split command in several HID packet memset(buffer, 0, sizeof(buffer)); - result = this->wrapCommand(command, cmd_len, buffer, sizeof(buffer)); + result = wrapCommand(command, cmd_len, buffer, sizeof(buffer)); remaining = result; while (remaining > 0) { @@ -193,94 +159,93 @@ namespace hw { memset(padding_buffer, 0, sizeof(padding_buffer)); memcpy(padding_buffer+1, buffer + offset, block_size); io_hid_log(0, padding_buffer, block_size+1); - hid_ret = hid_write(this->usb_device, padding_buffer, block_size+1); - ASSERT_X(hid_ret>=0, "Unable to send hidapi command. Error "+std::to_string(result)+": "+ safe_hid_error(this->usb_device)); - offset += block_size; + hid_ret = hid_write(usb_device, padding_buffer, block_size+1); + CHECK_AND_ASSERT_THROW_MES(hid_ret>=0, "Unable to send hidapi command. Error "+std::to_string(result)+": "+ safe_hid_error(usb_device)); offset += block_size; remaining -= block_size; } //get first response memset(buffer, 0, sizeof(buffer)); if (!user_input) { - hid_ret = hid_read_timeout(this->usb_device, buffer, MAX_BLOCK, this->timeout); + hid_ret = hid_read_timeout(usb_device, buffer, MAX_BLOCK, timeout); } else { - hid_ret = hid_read(this->usb_device, buffer, MAX_BLOCK); + hid_ret = hid_read(usb_device, buffer, MAX_BLOCK); } - ASSERT_X(hid_ret>=0, "Unable to read hidapi response. Error "+std::to_string(result)+": "+ safe_hid_error(this->usb_device)); + CHECK_AND_ASSERT_THROW_MES(hid_ret>=0, "Unable to read hidapi response. Error "+std::to_string(result)+": "+ safe_hid_error(usb_device)); result = (unsigned int)hid_ret; io_hid_log(1, buffer, result); offset = MAX_BLOCK; //parse first response and get others if any - for (;;) { - result = this->unwrapReponse(buffer, offset, response, max_resp_len); + while (true) { + result = unwrapReponse(buffer, offset, response, max_resp_len); if (result != 0) { break; } - hid_ret = hid_read_timeout(this->usb_device, buffer + offset, MAX_BLOCK, this->timeout); - ASSERT_X(hid_ret>=0, "Unable to receive hidapi response. Error "+std::to_string(result)+": "+ safe_hid_error(this->usb_device)); - result = (unsigned int)hid_ret; + hid_ret = hid_read_timeout(usb_device, buffer + offset, MAX_BLOCK, timeout); + CHECK_AND_ASSERT_THROW_MES(hid_ret>=0, "Unable to receive hidapi response. Error "+std::to_string(result)+": "+ safe_hid_error(usb_device)); + result = static_cast(hid_ret); io_hid_log(1, buffer + offset, result); offset += MAX_BLOCK; } return result; } - void device_io_hid::disconnect(void) { - if (this->usb_device) { - hid_close(this->usb_device); + void hid::disconnect(void) { + if (usb_device) { + hid_close(usb_device); } - this->usb_vid = 0; - this->usb_pid = 0; - this->usb_device = nullptr; + usb_vid = 0; + usb_pid = 0; + usb_device = nullptr; } - void device_io_hid::release() { + void hid::release() { /* Do not exit, as the lib context is global*/ //hid_exit(); } - unsigned int device_io_hid::wrapCommand(const unsigned char *command, size_t command_len, unsigned char *out, size_t out_len) { + unsigned int hid::wrapCommand(const unsigned char *command, size_t command_len, unsigned char *out, size_t out_len) { unsigned int sequence_idx = 0; unsigned int offset = 0; unsigned int offset_out = 0; unsigned int block_size; - ASSERT_X(this->packet_size >= 3, "Invalid Packet size: "+std::to_string(this->packet_size)) ; - ASSERT_X(out_len >= 7, "out_len too short: "+std::to_string(out_len)); + CHECK_AND_ASSERT_THROW_MES(packet_size >= 3, "Invalid Packet size: "+std::to_string(packet_size)) ; + CHECK_AND_ASSERT_THROW_MES(out_len >= 7, "out_len too short: "+std::to_string(out_len)); out_len -= 7; - out[offset_out++] = ((this->channel >> 8) & 0xff); - out[offset_out++] = (this->channel & 0xff); - out[offset_out++] = this->tag; + out[offset_out++] = ((channel >> 8) & 0xff); + out[offset_out++] = (channel & 0xff); + out[offset_out++] = tag; out[offset_out++] = ((sequence_idx >> 8) & 0xff); out[offset_out++] = (sequence_idx & 0xff); sequence_idx++; out[offset_out++] = ((command_len >> 8) & 0xff); out[offset_out++] = (command_len & 0xff); - block_size = (command_len > this->packet_size - 7 ? this->packet_size - 7 : command_len); - ASSERT_X(out_len >= block_size, "out_len too short: "+std::to_string(out_len)); + block_size = (command_len > packet_size - 7 ? packet_size - 7 : command_len); + CHECK_AND_ASSERT_THROW_MES(out_len >= block_size, "out_len too short: "+std::to_string(out_len)); out_len -= block_size; memcpy(out + offset_out, command + offset, block_size); offset_out += block_size; offset += block_size; while (offset != command_len) { - ASSERT_X(out_len >= 5, "out_len too short: "+std::to_string(out_len)); + CHECK_AND_ASSERT_THROW_MES(out_len >= 5, "out_len too short: "+std::to_string(out_len)); out_len -= 5; - out[offset_out++] = ((this->channel >> 8) & 0xff); - out[offset_out++] = (this->channel & 0xff); - out[offset_out++] = this->tag; + out[offset_out++] = ((channel >> 8) & 0xff); + out[offset_out++] = (channel & 0xff); + out[offset_out++] = tag; out[offset_out++] = ((sequence_idx >> 8) & 0xff); out[offset_out++] = (sequence_idx & 0xff); sequence_idx++; - block_size = ((command_len - offset) > this->packet_size - 5 ? this->packet_size - 5 : command_len - offset); - ASSERT_X(out_len >= block_size, "out_len too short: "+std::to_string(out_len)); + block_size = ((command_len - offset) > packet_size - 5 ? packet_size - 5 : command_len - offset); + CHECK_AND_ASSERT_THROW_MES(out_len >= block_size, "out_len too short: "+std::to_string(out_len)); out_len -= block_size; memcpy(out + offset_out, command + offset, block_size); offset_out += block_size; offset += block_size; } - while ((offset_out % this->packet_size) != 0) { - ASSERT_X(out_len >= 1, "out_len too short: "+std::to_string(out_len)); + while ((offset_out % packet_size) != 0) { + CHECK_AND_ASSERT_THROW_MES(out_len >= 1, "out_len too short: "+std::to_string(out_len)); out_len--; out[offset_out++] = 0; } @@ -291,7 +256,7 @@ namespace hw { * return 0 if more data are needed * >0 if response is fully available */ - unsigned int device_io_hid::unwrapReponse(const unsigned char *data, size_t data_len, unsigned char *out, size_t out_len) { + unsigned int hid::unwrapReponse(const unsigned char *data, size_t data_len, unsigned char *out, size_t out_len) { unsigned int sequence_idx = 0; unsigned int offset = 0; unsigned int offset_out = 0; @@ -307,22 +272,22 @@ namespace hw { //check hid header val = (data[offset]<<8) + data[offset+1]; offset += 2; - ASSERT_X(val == this->channel, "Wrong Channel"); + CHECK_AND_ASSERT_THROW_MES(val == channel, "Wrong Channel"); val = data[offset]; offset++; - ASSERT_X(val == this->tag, "Wrong TAG"); + CHECK_AND_ASSERT_THROW_MES(val == tag, "Wrong TAG"); val = (data[offset]<<8) + data[offset+1]; offset += 2; - ASSERT_X(val == sequence_idx, "Wrong sequence_idx"); + CHECK_AND_ASSERT_THROW_MES(val == sequence_idx, "Wrong sequence_idx"); //fetch response_len = (data[offset++] << 8); response_len |= data[offset++]; - ASSERT_X(out_len >= response_len, "Out Buffer too short"); + CHECK_AND_ASSERT_THROW_MES(out_len >= response_len, "Out Buffer too short"); if (data_len < (7 + response_len)) { return 0; } - block_size = (response_len > (this->packet_size - 7) ? this->packet_size - 7 : response_len); + block_size = (response_len > (packet_size - 7) ? packet_size - 7 : response_len); memcpy(out + offset_out, data + offset, block_size); offset += block_size; offset_out += block_size; @@ -333,15 +298,15 @@ namespace hw { } val = (data[offset]<<8) + data[offset+1]; offset += 2; - ASSERT_X(val == this->channel, "Wrong Channel"); + CHECK_AND_ASSERT_THROW_MES(val == channel, "Wrong Channel"); val = data[offset]; offset++; - ASSERT_X(val == this->tag, "Wrong TAG"); + CHECK_AND_ASSERT_THROW_MES(val == tag, "Wrong TAG"); val = (data[offset]<<8) + data[offset+1]; offset += 2; - ASSERT_X(val == sequence_idx, "Wrong sequence_idx"); + CHECK_AND_ASSERT_THROW_MES(val == sequence_idx, "Wrong sequence_idx"); - block_size = ((response_len - offset_out) > this->packet_size - 5 ? this->packet_size - 5 : response_len - offset_out); + block_size = ((response_len - offset_out) > packet_size - 5 ? packet_size - 5 : response_len - offset_out); if (block_size > (data_len - offset)) { return 0; } @@ -352,8 +317,6 @@ namespace hw { return offset_out; } - - } } #endif //#if defined(HAVE_HIDAPI) diff --git a/src/device/device_io_hid.hpp b/src/device/io_hid.hpp similarity index 70% rename from src/device/device_io_hid.hpp rename to src/device/io_hid.hpp index 905373d1c89..de45d14013a 100755 --- a/src/device/device_io_hid.hpp +++ b/src/device/io_hid.hpp @@ -30,8 +30,9 @@ #if defined(HAVE_HIDAPI) #include +#include #include -#include "device_io.hpp" +#include "io_device.hpp" #pragma once @@ -58,26 +59,21 @@ namespace hw { }; - class device_io_hid: device_io { + class hid : public device { - - private: - - - unsigned short channel; - unsigned char tag; - unsigned int packet_size; - unsigned int timeout; - - unsigned int usb_vid; - unsigned int usb_pid; - hid_device *usb_device; + unsigned short channel = 0x0001; + unsigned char tag = 0x01; + unsigned int packet_size = 64; + unsigned int timeout = 120000; + unsigned int usb_vid = 0; + unsigned int usb_pid = 0; + hid_device* usb_device = nullptr; void io_hid_log(int read, unsigned char* buf, int buf_len); void io_hid_init(); void io_hid_exit() ; void io_hid_open(int vid, int pid, int mode); - void io_hid_close (void); + void io_hid_close (); unsigned int wrapCommand(const unsigned char *command, size_t command_len, unsigned char *out, size_t out_len); unsigned int unwrapReponse(const unsigned char *data, size_t data_len, unsigned char *out, size_t out_len); @@ -87,23 +83,16 @@ namespace hw { public: bool hid_verbose = false; - static const unsigned short DEFAULT_CHANNEL = 0x0001; - static const unsigned char DEFAULT_TAG = 0x01; - static const unsigned int DEFAULT_PACKET_SIZE = 64; - static const unsigned int DEFAULT_TIMEOUT = 120000; - - device_io_hid(unsigned short channel, unsigned char tag, unsigned int packet_zize, unsigned int timeout); - device_io_hid(); - ~device_io_hid() {}; + hid(unsigned short channel, unsigned char tag, unsigned int packet_zize, unsigned int timeout); + hid() = default; - void init(); - void connect(void *params); - void connect(const std::vector &conn); - hid_device *connect(unsigned int vid, unsigned int pid, std::optional interface_number, std::optional usage_page); - bool connected() const; - int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input); - void disconnect(); - void release(); + void init() override; + void connect(const std::vector& conn); + bool connect(unsigned int vid, unsigned int pid, std::optional interface_number, std::optional usage_page); + bool connected() const override; + int exchange(unsigned char* command, unsigned int cmd_len, unsigned char* response, unsigned int max_resp_len, bool user_input) override; + void disconnect() override; + void release() override; }; }; }; diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 6dc85e8a01b..e57115b6cda 100755 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -1190,7 +1190,7 @@ namespace rct { if (rct_config.range_proof_type == RangeProofType::PaddedBulletproof) { rct::keyV C, masks; - if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE) + if (hwdev.get_mode() == hw::device::mode::TRANSACTION_CREATE_FAKE) { // use a fake bulletproof for speed rv.p.bulletproofs.push_back(make_dummy_bulletproof(outamounts, C, masks)); @@ -1219,7 +1219,7 @@ namespace rct { std::vector batch_amounts(batch_size); for (i = 0; i < batch_size; ++i) batch_amounts[i] = outamounts[i + amounts_proved]; - if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE) + if (hwdev.get_mode() == hw::device::mode::TRANSACTION_CREATE_FAKE) { // use a fake bulletproof for speed rv.p.bulletproofs.push_back(make_dummy_bulletproof(batch_amounts, C, masks)); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 44c89bff17f..4de4e9d2f1a 100755 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -4464,7 +4464,7 @@ std::optional simple_wallet::open_wallet(const boost::pro prefix = tr("Opened wallet"); message_writer(epee::console_color_green, true) << prefix << ": " << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); - if (m_wallet->get_account().get_device()) { + if (m_wallet->get_account().get_device().is_hardware_device()) { message_writer(epee::console_color_white, true) << "Wallet is on device: " << m_wallet->get_account().get_device().get_name(); } // If the wallet file is deprecated, we should ask for mnemonic language again and store @@ -7867,7 +7867,7 @@ bool simple_wallet::get_tx_key(const std::vector &args_) { std::vector local_args = args_; - if (m_wallet->key_on_device() && m_wallet->get_account().get_device().get_type() != hw::device::TREZOR) + if (m_wallet->key_on_device() && m_wallet->get_account().get_device().get_type() != hw::device::type::TREZOR) { fail_msg_writer() << tr("command not supported by HW wallet"); return true; diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index dc48ff73161..010782eff98 100755 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -170,7 +170,7 @@ bool WalletManagerImpl::verifyWalletPassword(std::string_view keys_file_name, co EXPORT bool WalletManagerImpl::queryWalletDevice(Wallet::Device& device_type, std::string_view keys_file_name, const std::string &password, uint64_t kdf_rounds) const { - hw::device::device_type type; + hw::device::type type; bool r = tools::wallet2::query_device(type, fs::u8path(keys_file_name), password, kdf_rounds); device_type = static_cast(type); return r; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6b3327640f3..f3cdb86b077 100755 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1075,7 +1075,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_light_wallet_unlocked_balance(0), m_original_keys_available(false), m_message_store(), - m_key_device_type(hw::device::device_type::SOFTWARE), + m_key_device_type(hw::device::type::type::SOFTWARE), m_ring_history_saved(false), m_ringdb(), m_last_block_reward(0), @@ -1635,7 +1635,7 @@ void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivatio { hw::device &hwdev = m_account.get_device(); std::unique_lock hwdev_lock{hwdev}; - hwdev.set_mode(hw::device::TRANSACTION_PARSE); + hwdev.set_mode(hw::device::mode::TRANSACTION_PARSE); if (!std::holds_alternative(o.target)) { tx_scan_info.error = true; @@ -1914,7 +1914,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote std::unique_lock hwdev_lock{hwdev}; hw::mode_resetter rst{hwdev}; - hwdev.set_mode(hw::device::TRANSACTION_PARSE); + hwdev.set_mode(hw::device::mode::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 in " << txid << ", skipping"); @@ -1978,7 +1978,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote hw::device &hwdev = m_account.get_device(); std::unique_lock hwdev_lock{hwdev}; - hwdev.set_mode(hw::device::NONE); + hwdev.set_mode(hw::device::mode::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()); @@ -1999,7 +1999,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote { hw::device &hwdev = m_account.get_device(); std::unique_lock hwdev_lock{hwdev}; - hwdev.set_mode(hw::device::NONE); + hwdev.set_mode(hw::device::mode::NONE); hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations); scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], tx_money_got_in_outs, outs, pool, flash); } @@ -2776,7 +2776,7 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector wallet2::get_keys_file_data(const epee::w rapidjson::Value value2(rapidjson::kNumberType); - value2.SetInt(m_key_device_type); + value2.SetInt(static_cast(m_key_device_type)); json.AddMember("key_on_device", value2, json.GetAllocator()); value2.SetInt(watch_only ? 1 :0); // WTF ? JSON has different true and false types, and not boolean ?? @@ -4229,7 +4229,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_original_keys_available = false; m_device_name = ""; m_device_derivation_path = ""; - m_key_device_type = hw::device::device_type::SOFTWARE; + m_key_device_type = hw::device::type::SOFTWARE; encrypted_secret_keys = false; } else if(json.IsObject()) @@ -4249,8 +4249,8 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st if (json.HasMember("key_on_device")) { - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, key_on_device, int, Int, false, hw::device::device_type::SOFTWARE); - m_key_device_type = static_cast(field_key_on_device); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, key_on_device, int, Int, false, hw::device::type::SOFTWARE); + m_key_device_type = static_cast(field_key_on_device); } GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, seed_language, std::string, String, false, std::string()); @@ -4401,7 +4401,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st } else { - m_device_name = m_key_device_type == hw::device::device_type::LEDGER ? "Ledger" : "default"; + m_device_name = m_key_device_type == hw::device::type::LEDGER ? "Ledger" : "default"; } } @@ -4445,7 +4445,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st bool r = epee::serialization::load_t_from_binary(m_account, account_data); THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password); - if (m_key_device_type == hw::device::device_type::LEDGER || m_key_device_type == hw::device::device_type::TREZOR) { + if (m_key_device_type == hw::device::type::LEDGER || m_key_device_type == hw::device::type::TREZOR) { LOG_PRINT_L0("Account on device. Initing device..."); hw::device &hwdev = lookup_device(m_device_name); THROW_WALLET_EXCEPTION_IF(!hwdev.set_name(m_device_name), error::wallet_internal_error, "Could not set device name " + m_device_name); @@ -4482,7 +4482,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st const cryptonote::account_keys& keys = m_account.get_keys(); hw::device &hwdev = m_account.get_device(); r = r && hwdev.verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key); - if (!m_watch_only && !m_multisig && hwdev.device_protocol() != hw::device::PROTOCOL_COLD) + if (!m_watch_only && !m_multisig && hwdev.device_protocol() != hw::device::protocol::COLD)) r = r && hwdev.verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_files_doesnt_correspond, m_keys_file, m_wallet_file); @@ -4506,7 +4506,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password) { // this temporary unlocking is necessary for Windows (otherwise the file couldn't be loaded). unlock_keys_file(); - bool r = verify_password(m_keys_file, password, m_account.get_device().device_protocol() == hw::device::PROTOCOL_COLD || m_watch_only || m_multisig, m_account.get_device(), m_kdf_rounds); + bool r = verify_password(m_keys_file, password, m_account.get_device().device_protocol() == hw::device::protocol::COLD) || m_watch_only || m_multisig, m_account.get_device(), m_kdf_rounds); lock_keys_file(); return r; } @@ -4636,7 +4636,7 @@ void wallet2::create_keys_file(const fs::path &wallet_, bool watch_only, const e /*! * \brief determine the key storage for the specified wallet file - * \param device_type (OUT) wallet backend as enumerated in hw::device::device_type + * \param device_type (OUT) wallet backend as enumerated in hw::device::type * \param keys_file_name Keys file to verify password for * \param password Password to verify * \return true if password correct, else false @@ -4644,7 +4644,7 @@ void wallet2::create_keys_file(const fs::path &wallet_, bool watch_only, const e * for verification only - determines key storage hardware * */ -bool wallet2::query_device(hw::device::device_type& device_type, const fs::path& keys_file_name, const epee::wipeable_string& password, uint64_t kdf_rounds) +bool wallet2::query_device(hw::device::type& device_type, const fs::path& keys_file_name, const epee::wipeable_string& password, uint64_t kdf_rounds) { rapidjson::Document json; wallet2::keys_file_data keys_file_data; @@ -4666,7 +4666,7 @@ bool wallet2::query_device(hw::device::device_type& device_type, const fs::path& if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject()) crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); - device_type = hw::device::device_type::SOFTWARE; + device_type = hw::device::type::SOFTWARE; // The contents should be JSON if the wallet follows the new format. if (json.Parse(account_data.c_str()).HasParseError()) { @@ -4679,8 +4679,8 @@ bool wallet2::query_device(hw::device::device_type& device_type, const fs::path& if (json.HasMember("key_on_device")) { - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, key_on_device, int, Int, false, hw::device::device_type::SOFTWARE); - device_type = static_cast(field_key_on_device); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, key_on_device, int, Int, false, hw::device::type::SOFTWARE); + device_type = static_cast(field_key_on_device); } } @@ -4691,7 +4691,7 @@ bool wallet2::query_device(hw::device::device_type& device_type, const fs::path& return true; } -void wallet2::init_type(hw::device::device_type device_type) +void wallet2::init_type(hw::device::type device_type) { m_account_public_address = m_account.get_keys().m_account_address; m_watch_only = false; @@ -4774,7 +4774,7 @@ void wallet2::generate(const fs::path& wallet_, const epee::wipeable_string& pas // Not possible to restore a multisig wallet that is able to activate the MMS // (because the original keys are not (yet) part of the restore info), so // keep m_original_keys_available to false - init_type(hw::device::device_type::SOFTWARE); + init_type(hw::device::type::SOFTWARE); m_multisig = true; m_multisig_threshold = threshold; m_multisig_signers = multisig_signers; @@ -4812,7 +4812,7 @@ crypto::secret_key wallet2::generate(const fs::path& wallet_, const epee::wipeab crypto::secret_key retval = m_account.generate(recovery_param, recover, two_random); - init_type(hw::device::device_type::SOFTWARE); + init_type(hw::device::type::SOFTWARE); setup_keys(password); // calculate a starting refresh height @@ -4891,7 +4891,7 @@ void wallet2::generate(const fs::path& wallet_, const epee::wipeable_string& pas } m_account.create_from_viewkey(account_public_address, viewkey); - init_type(hw::device::device_type::SOFTWARE); + init_type(hw::device::type::SOFTWARE); m_watch_only = true; m_account_public_address = account_public_address; setup_keys(password); @@ -4928,7 +4928,7 @@ void wallet2::generate(const fs::path& wallet_, const epee::wipeable_string& pas } m_account.create_from_keys(account_public_address, spendkey, viewkey); - init_type(hw::device::device_type::SOFTWARE); + init_type(hw::device::type::SOFTWARE); m_account_public_address = account_public_address; setup_keys(password); @@ -5110,7 +5110,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password, "Failed to create multisig wallet due to bad keys"); memwipe(&spend_skey, sizeof(rct::key)); - init_type(hw::device::device_type::SOFTWARE); + init_type(hw::device::type::SOFTWARE); m_original_keys_available = true; m_multisig = true; m_multisig_threshold = threshold; @@ -7202,7 +7202,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, 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; - hwdev.set_mode(hw::device::TRANSACTION_CREATE_FAKE); + hwdev.set_mode(hw::device::mode::TRANSACTION_CREATE_FAKE); while ((!dsts.empty() && dsts[0].amount > 0) || adding_fee || !preferred_inputs.empty() || should_pick_a_second_output(txes.back().selected_transfers.size(), *unused_transfers_indices, *unused_dust_indices)) { TX &tx = txes.back(); @@ -11313,7 +11313,7 @@ std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_from(const crypton needed_fee = 0; // while we have something to send - hwdev.set_mode(hw::device::TRANSACTION_CREATE_FAKE); + hwdev.set_mode(hw::device::mode::TRANSACTION_CREATE_FAKE); while (!unused_dust_indices.empty() || !unused_transfers_indices.empty()) { TX &tx = txes.back(); @@ -11686,7 +11686,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_mode(hw::device::TRANSACTION_CREATE_REAL); + hwdev.set_mode(hw::device::mode::TRANSACTION_CREATE_REAL); for (auto &tx : txes) { // Convert burn percent into a fixed burn amount because this is the last place we can back out @@ -12019,7 +12019,7 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, s auto & hwdev = get_account().get_device(); // So far only Cold protocol devices are supported. - if (hwdev.device_protocol() != hw::device::PROTOCOL_COLD) + if (hwdev.device_protocol() != hw::device::protocol::COLD)) { return false; } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 8f494abba96..b25290b2614 100755 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -292,7 +292,7 @@ namespace tools const std::function(const char *, bool)> &password_prompter); static bool verify_password(const fs::path& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev, uint64_t kdf_rounds); - static bool query_device(hw::device::device_type& device_type, const fs::path& keys_file_name, const epee::wipeable_string& password, uint64_t kdf_rounds = 1); + static bool query_device(hw::device::type& device_type, const fs::path& keys_file_name, const epee::wipeable_string& password, uint64_t kdf_rounds = 1); wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, uint64_t kdf_rounds = 1, bool unattended = false); ~wallet2(); @@ -715,8 +715,8 @@ namespace tools bool has_multisig_partial_key_images() const; bool has_unknown_key_images() const; bool get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase = std::string(), bool raw = true) const; - bool key_on_device() const { return get_device_type() != hw::device::device_type::SOFTWARE; } - hw::device::device_type get_device_type() const { return m_key_device_type; } + bool key_on_device() const { return get_device_type() != hw::device::type::SOFTWARE; } + hw::device::type get_device_type() const { return m_key_device_type; } bool reconnect_device(); // locked & unlocked balance of given or current subaddress account @@ -1549,7 +1549,7 @@ namespace tools void cache_tx_data(const cryptonote::transaction& tx, const crypto::hash &txid, tx_cache_data &tx_cache_data) const; std::shared_ptr, size_t>> create_output_tracker_cache() const; - void init_type(hw::device::device_type device_type); + void init_type(hw::device::type device_type); void setup_new_blockchain(); void create_keys_file(const fs::path &wallet_, bool watch_only, const epee::wipeable_string &password, bool create_address_file); @@ -1601,7 +1601,7 @@ namespace tools bool m_trusted_daemon; i_wallet2_callback* m_callback; - hw::device::device_type m_key_device_type; + hw::device::type m_key_device_type; cryptonote::network_type m_nettype; uint64_t m_kdf_rounds; std::string seed_language; /*!< Language of the mnemonics (seed). */ From e492eb4ba4b0b2d39f86977a7ddd104b52867a4d Mon Sep 17 00:00:00 2001 From: victor-tucci Date: Wed, 14 Jun 2023 15:04:35 +0530 Subject: [PATCH 3/3] Add LedgerTCP hardware wallet support --- cmake/StaticBuild.cmake | 1 + src/device/CMakeLists.txt | 3 +- src/device/device.hpp | 4 + src/device/device_ledger.cpp | 50 +++++++-- src/device/device_ledger.hpp | 16 ++- src/device/io_device.hpp | 2 +- src/device/io_hid.cpp | 2 +- src/device/io_hid.hpp | 2 +- src/device/io_ledger_tcp.cpp | 192 +++++++++++++++++++++++++++++++++++ src/device/io_ledger_tcp.hpp | 41 ++++++++ src/wallet/wallet2.cpp | 13 ++- src/wallet/wallet2.h | 7 +- 12 files changed, 309 insertions(+), 24 deletions(-) create mode 100644 src/device/io_ledger_tcp.cpp create mode 100644 src/device/io_ledger_tcp.hpp diff --git a/cmake/StaticBuild.cmake b/cmake/StaticBuild.cmake index 3c28e9f5a5f..244b4c7a906 100755 --- a/cmake/StaticBuild.cmake +++ b/cmake/StaticBuild.cmake @@ -495,6 +495,7 @@ build_external(zmq ${zmq_patch} CONFIGURE_COMMAND ./configure ${zmq_cross_host} --prefix=${DEPS_DESTDIR} --enable-static --disable-shared --disable-curve-keygen --enable-curve --disable-drafts --disable-libunwind --with-libsodium + --disable-libbsd --disable-perf --without-pgm --without-norm --without-vmci --without-docs --with-pic --disable-Werror "CC=${deps_cc}" "CXX=${deps_cxx}" "CFLAGS=-fstack-protector ${deps_CFLAGS}" "CXXFLAGS=-fstack-protector ${deps_CXXFLAGS}" ${cross_extra} diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 62ed7942893..54d6783342e 100755 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -68,7 +68,8 @@ endif() if (HIDAPI_FOUND) target_sources(device PRIVATE device_ledger.cpp - device_io_hid.cpp + io_hid.cpp + io_ledger_tcp.cpp ) target_link_libraries(device PRIVATE hidapi_libusb) endif() diff --git a/src/device/device.hpp b/src/device/device.hpp index 4083d31cc31..81a5e64e348 100755 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -119,6 +119,10 @@ namespace hw { virtual bool set_name(std::string_view name) = 0; virtual std::string get_name() const = 0; + // Optional; can be used to take an address parameter if required (e.g. Ledger TCP uses this + // to specify the TCP address). + virtual void set_address(std::string_view address) {} + virtual bool init() = 0; virtual bool release() = 0; diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index fdc6e1c2d2c..7887d8f8dfa 100755 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -28,6 +28,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#include "io_ledger_tcp.hpp" #include "io_hid.hpp" #include "version.h" #include "device_ledger.hpp" @@ -312,7 +313,7 @@ static_assert(BLAKE2B_HASH_CHUNK_SIZE <= 254, "Max BLAKE2b data chunk size exceeds the protocol limit"); - device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 2000) { + device_ledger::device_ledger() : hw_device{std::make_unique(0x0101, 0x05, 64, 2000)} { id = device_id++; reset_buffer(); has_view_key = false; @@ -320,6 +321,14 @@ MDEBUG("Device " << id << " Created"); } + device_ledger::device_ledger(io::ledger_tcp&& tcp) : hw_device{std::make_unique(std::move(tcp))} { + id = device_id++; + reset_buffer(); + has_view_key = false; + tx_in_progress = false; + MDEBUG("Device " << id << " (tcp) created"); + } + device_ledger::~device_ledger() { release(); MDEBUG("Device " << id << " Destroyed"); @@ -496,7 +505,7 @@ unsigned int device_ledger::exchange(bool wait_on_input) { logCMD(); - length_recv = hw_device.exchange(buffer_send, length_send, buffer_recv, BUFFER_SEND_SIZE, wait_on_input); + length_recv = hw_device->exchange(buffer_send, length_send, buffer_recv, BUFFER_RECV_SIZE, wait_on_input); CHECK_AND_ASSERT_THROW_MES(length_recv >= 2, "Communication error, less than two bytes received"); length_recv -= 2; @@ -517,7 +526,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int mask) { logCMD(); unsigned int deny = 0; - this->length_recv = hw_device.exchange(this->buffer_send, this->length_send, this->buffer_recv, BUFFER_SEND_SIZE, true); + this->length_recv = hw_device->exchange(this->buffer_send, this->length_send, this->buffer_recv, BUFFER_SEND_SIZE, true); CHECK_AND_ASSERT_THROW_MES(this->length_recv>=2, "Communication error, less than two bytes received"); this->length_recv -= 2; @@ -555,24 +564,42 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int return name; } + void device_ledger::set_address(std::string_view addr) { + if (addr.empty() || !hw_device) + return; + auto* tcp = dynamic_cast(hw_device.get()); + if (!tcp) + return; + if (auto pos = addr.rfind(':'); pos != addr.npos) { + tcp->port = addr.substr(pos + 1); + addr = addr.substr(0, pos); + } + tcp->host = addr; + } + bool device_ledger::init() { #ifdef DEBUG_HWDEVICE debug_device = &get_device("default"); #endif release(); - hw_device.init(); + hw_device->init(); MDEBUG("Device " << id <<" HIDUSB inited"); return true; } static const std::vector known_devices { - {0x2c97, 0x0001, 0, 0xffa0}, - {0x2c97, 0x0004, 0, 0xffa0}, + {0x2c97, 0x1000, 0, 0xffa0}, + {0x2c97, 0x4000, 0, 0xffa0}, }; bool device_ledger::connect() { disconnect(); - hw_device.connect(known_devices); + if (auto* hid_io = dynamic_cast(hw_device.get())) + hid_io->connect(known_devices); + else if (auto* tcp = dynamic_cast(hw_device.get())) + tcp->connect(); + else + throw std::logic_error{"Invalid ledger hardware configure"}; reset(); check_network_type(); @@ -589,17 +616,17 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int } bool device_ledger::connected() const { - return hw_device.connected(); + return hw_device->connected(); } bool device_ledger::disconnect() { - hw_device.disconnect(); + hw_device->disconnect(); return true; } bool device_ledger::release() { disconnect(); - hw_device.release(); + hw_device->release(); return true; } @@ -639,7 +666,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int case mode::TRANSACTION_CREATE_REAL: case mode::TRANSACTION_CREATE_FAKE: { - offset = set_command_header_noopt(INS_SET_SIGNATURE_MODE, 1); + int offset = set_command_header_noopt(INS_SET_SIGNATURE_MODE, 1); buffer_send[offset++] = static_cast(m); finish_and_exchange(offset); @@ -2294,6 +2321,7 @@ unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int void register_all(std::map>& registry) { registry.emplace("Ledger", std::make_unique()); + registry.emplace("LedgerTCP", std::make_unique(io::ledger_tcp{})); } #else //WITH_DEVICE_LEDGER diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index 68dc0cabb90..d9697bece1c 100755 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -34,6 +34,7 @@ #include #include #include "device.hpp" +#include "io_ledger_tcp.hpp" #include "log.hpp" #include "io_hid.hpp" @@ -142,7 +143,7 @@ namespace hw::ledger { mutable std::mutex command_locker; //IO - hw::io::hid hw_device; + std::unique_ptr hw_device; unsigned int length_send; unsigned char buffer_send[BUFFER_SEND_SIZE]; unsigned int length_recv; @@ -204,10 +205,17 @@ namespace hw::ledger { public: device_ledger(); + + // Constructs a ledger device object that uses a TCP socket to communicate with the ledger + // device, typically for use with a Ledger emulator which doesn't emulated the USB layer. + explicit device_ledger(io::ledger_tcp&& tcp); + ~device_ledger(); - device_ledger(const device_ledger &device) = delete ; - device_ledger& operator=(const device_ledger &device) = delete; + device_ledger(const device_ledger&) = delete ; + device_ledger(device_ledger&&) = delete ; + device_ledger& operator=(const device_ledger&) = delete; + device_ledger&& operator=(device_ledger&&) = delete; bool is_hardware_device() const override {return connected(); } @@ -218,6 +226,8 @@ namespace hw::ledger { /* ======================================================================= */ bool set_name(std::string_view name) override; + void set_address(std::string_view addr) override; + std::string get_name() const override; bool init() override; bool release() override; diff --git a/src/device/io_device.hpp b/src/device/io_device.hpp index 4589b8dca68..c5e8a5455ea 100755 --- a/src/device/io_device.hpp +++ b/src/device/io_device.hpp @@ -47,7 +47,7 @@ namespace hw::io { virtual void disconnect() = 0; virtual bool connected() const = 0; - virtual int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) = 0; + virtual int exchange(const unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) = 0; }; } diff --git a/src/device/io_hid.cpp b/src/device/io_hid.cpp index 8f712aacc25..59166b5c523 100755 --- a/src/device/io_hid.cpp +++ b/src/device/io_hid.cpp @@ -138,7 +138,7 @@ namespace hw::io { return usb_device != nullptr; } - int hid::exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) { + int hid::exchange(const unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) { unsigned char buffer[400]; unsigned char padding_buffer[MAX_BLOCK+1]; unsigned int result; diff --git a/src/device/io_hid.hpp b/src/device/io_hid.hpp index de45d14013a..2a64c522ed1 100755 --- a/src/device/io_hid.hpp +++ b/src/device/io_hid.hpp @@ -90,7 +90,7 @@ namespace hw { void connect(const std::vector& conn); bool connect(unsigned int vid, unsigned int pid, std::optional interface_number, std::optional usage_page); bool connected() const override; - int exchange(unsigned char* command, unsigned int cmd_len, unsigned char* response, unsigned int max_resp_len, bool user_input) override; + int exchange(const unsigned char* command, unsigned int cmd_len, unsigned char* response, unsigned int max_resp_len, bool user_input) override; void disconnect() override; void release() override; }; diff --git a/src/device/io_ledger_tcp.cpp b/src/device/io_ledger_tcp.cpp new file mode 100644 index 00000000000..e768908a527 --- /dev/null +++ b/src/device/io_ledger_tcp.cpp @@ -0,0 +1,192 @@ +#include "io_ledger_tcp.hpp" +#include "common/beldex.h" +#include +#include +#include +#include +#include "epee/misc_log_ex.h" + +extern "C" { +#ifdef _WIN32 +# include +# include +#else +# include +# include +# include +# include +#endif +#include +#include +#include +} + +#undef BELDEX_DEFAULT_LOG_CATEGORY +#define BELDEX_DEFAULT_LOG_CATEGORY "device.io" + +namespace hw::io { + +static std::string to_string(const addrinfo* a) { + std::array buf; + std::string addr; +#ifdef _WIN32 + unsigned long buflen = buf.size(); + if (auto rc = WSAAddressToString(a->ai_addr, a->ai_addrlen, nullptr, buf.data(), &buflen); + rc == 0) + addr = buf.data(); + else + addr = "[error:"s + std::to_string(rc) + "]"; +#else + if (inet_ntop(a->ai_family, a->ai_addr, buf.data(), buf.size())) + addr = buf.data(); + else + addr = "[error:"s + strerror(errno) + "]"; +#endif + if (a->ai_family == AF_INET) + (addr += ':') += std::to_string(reinterpret_cast(a->ai_addr)->sin_port); + else if (a->ai_family == AF_INET6) + (addr += ':') += std::to_string(reinterpret_cast(a->ai_addr)->sin6_port); + return addr; +} + +void ledger_tcp::connect() { + disconnect(); + + int fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) + throw std::runtime_error{"Failed to open socket: "s + strerror(errno)}; + auto closer = beldex::defer([&] { close(fd); }); + +#ifdef _WIN32 + unsigned long blocking_param = 1; // 1 = make non-blocking, 0 = blocking + if (auto result = ioctlsocket(fd, FIONBIO, &blocking_param); + result != NO_ERROR) + throw std::runtime_error{"ioctlsocket failed with error: " + std::to_string(result)}; +#else + if (-1 == fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK)) + throw std::runtime_error{"Failed to set socket non-blocking: "s + strerror(errno)}; +#endif + + addrinfo* addr; + if (int rc = getaddrinfo(host.data(), port.data(), nullptr, &addr); + rc != 0) + throw std::runtime_error{"Failed to resolve " + host + ":" + port + ": " + gai_strerror(rc)}; + auto addr_free = beldex::defer([&] { freeaddrinfo(addr); }); + + const addrinfo* a; + bool connected = false; + const char* err = "An unknown error occurred"; + for (a = addr; a && !connected; a = a->ai_next) { + MDEBUG("Attempting to connect to " << to_string(a)); + int rc = ::connect(fd, a->ai_addr, a->ai_addrlen); + connected = rc == 0; + if (rc == -1) { + if (errno == EINPROGRESS) { + timeval timeo; + timeo.tv_sec = std::chrono::duration_cast(connect_timeout).count(); + timeo.tv_usec = (connect_timeout % 1s).count(); + fd_set myset; + FD_ZERO(&myset); + FD_SET(fd, &myset); + rc = select(fd + 1, nullptr, &myset, nullptr, &timeo); + if (rc > 0) + connected = true; + else if (rc == 0) + err = "Connection timed out"; + else + err = strerror(errno); + } else { + err = strerror(errno); + } + } + } + if (!connected) + throw std::runtime_error{"Failed to connect to " + host + ":" + port + ": " + err}; + + MDEBUG("Connected to " << to_string(a)); + +#ifdef _WIN32 + blocking_param = 0; + if (auto result = ioctlsocket(fd, FIONBIO, &blocking_param); + result != NO_ERROR) + throw std::runtime_error{"ioctlsocket failed with error: " + std::to_string(result)}; +#else + if (-1 == fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK)) + throw std::runtime_error{"Failed to set socket back to blocking: "s + strerror(errno)}; +#endif + + timeval timeo; + timeo.tv_sec = std::chrono::duration_cast(exchange_timeout).count(); + timeo.tv_usec = (exchange_timeout % 1s).count(); + + // The reinterpret_cast here is needed for Windows's shitty imitation of the api + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast(&timeo), sizeof(timeo)); + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast(&timeo), sizeof(timeo)); + + sockfd = std::make_unique(fd); + closer.cancel(); +} + +void ledger_tcp::disconnect() { + if (!sockfd) + return; + + close(*sockfd); + sockfd.reset(); +} + +ledger_tcp::~ledger_tcp() { + disconnect(); +} + +bool ledger_tcp::connected() const { + return (bool) sockfd; +} + +void full_read(int fd, unsigned char* to, int size) { + while (size > 0) { + auto read_size = read(fd, to, size); + if (read_size == -1) + throw std::runtime_error{"Failed to read from hardware wallet socket: "s + strerror(errno)}; + size -= read_size; + to += read_size; + } +} + +void full_write(int fd, const unsigned char* from, int size) { + while (size > 0) { + auto wrote = write(fd, from, size); + if (wrote == -1) + throw std::runtime_error{"Failed to write to hardware wallet socket: "s + strerror(errno)}; + size -= wrote; + from += wrote; + } +} + +int ledger_tcp::exchange(const unsigned char* command, unsigned int cmd_len, unsigned char* response, unsigned int max_resp_len, bool user_input) { + if (!sockfd) + throw std::runtime_error{"Unable to exchange data with hardware wallet: not connected"}; + + // Sending: [SIZE][DATA], where SIZE is a uint32_t in network order + uint32_t size = boost::endian::native_to_big(cmd_len); + const unsigned char* size_bytes = reinterpret_cast(&size); + full_write(*sockfd, size_bytes, 4); + full_write(*sockfd, command, cmd_len); + + + // Receiving: [SIZE][DATA], where SIZE is the length of DATA minus 2 (WTF) because the last two + // bytes of DATA are a 2-byte, u16 status code and... therefore not... included. Good job, Ledger + // devs. + full_read(*sockfd, reinterpret_cast(&size), 4); + auto data_size = boost::endian::big_to_native(size) + 2; + + if (data_size > max_resp_len) + throw std::runtime_error{"Hardware wallet returned unexpectedly large response: got " + + std::to_string(data_size) + " bytes, expected <= " + std::to_string(max_resp_len)}; + + full_read(*sockfd, response, data_size); + + return data_size; +} + +} diff --git a/src/device/io_ledger_tcp.hpp b/src/device/io_ledger_tcp.hpp new file mode 100644 index 00000000000..0ec3e37f3a7 --- /dev/null +++ b/src/device/io_ledger_tcp.hpp @@ -0,0 +1,41 @@ +// TCP APDU interface, as used by Ledger's emulator system (Speculos). + +#pragma once + +#include +#include +#include +#include "io_device.hpp" + +#pragma once + +namespace hw::io { + +using namespace std::literals; + +class ledger_tcp : public device { + + std::unique_ptr sockfd; + +public: + std::string host = "localhost"; + std::string port = "9999"; + + std::chrono::microseconds connect_timeout = 10s; + std::chrono::microseconds exchange_timeout = 120s; + + ledger_tcp() = default; + ~ledger_tcp() override; + + ledger_tcp(ledger_tcp&&) = default; + ledger_tcp& operator=(ledger_tcp&&) = default; + + void init() override {} + void release() override {} + void connect(); + bool connected() const override; + int exchange(const unsigned char* command, unsigned int cmd_len, unsigned char* response, unsigned int max_resp_len, bool user_input) override; + void disconnect() override; +}; + +} \ No newline at end of file diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index f3cdb86b077..3a945edf3fd 100755 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -277,6 +277,7 @@ struct options { }; const command_line::arg_descriptor kdf_rounds = {"kdf-rounds", tools::wallet2::tr("Number of rounds for the key derivation function"), 1}; const command_line::arg_descriptor hw_device = {"hw-device", tools::wallet2::tr("HW device to use"), ""}; + const command_line::arg_descriptor hw_device_address = {"hw-device-address", tools::wallet2::tr("HW device address, if required"), ""}; const command_line::arg_descriptor hw_device_derivation_path = {"hw-device-deriv-path", tools::wallet2::tr("HW device wallet derivation path (e.g., SLIP-10)"), ""}; const command_line::arg_descriptor tx_notify = { "tx-notify" , "Run a program for each new incoming transaction, '%s' will be replaced by the transaction hash" , "" }; const command_line::arg_descriptor offline = {"offline", tools::wallet2::tr("Do not connect to a daemon"), false}; @@ -334,6 +335,7 @@ std::unique_ptr make_basic(const boost::program_options::variabl auto daemon_port = command_line::get_arg(vm, opts.daemon_port); auto device_name = command_line::get_arg(vm, opts.hw_device); + auto device_addr = command_line::get_arg(vm, opts.hw_device_address); auto device_derivation_path = command_line::get_arg(vm, opts.hw_device_derivation_path); THROW_WALLET_EXCEPTION_IF(!daemon_address.empty() && (!daemon_host.empty() || 0 != daemon_port), @@ -406,6 +408,7 @@ std::unique_ptr make_basic(const boost::program_options::variabl wallet->set_ring_database(ringdb_path); wallet->get_message_store().set_options(vm); wallet->device_name(device_name); + wallet->device_address(device_addr); wallet->device_derivation_path(device_derivation_path); wallet->m_long_poll_disabled = command_line::get_arg(vm, opts.disable_rpc_long_poll); wallet->m_http_client.set_https_client_cert(command_line::get_arg(vm, opts.daemon_ssl_certificate), command_line::get_arg(vm, opts.daemon_ssl_private_key)); @@ -1075,7 +1078,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_light_wallet_unlocked_balance(0), m_original_keys_available(false), m_message_store(), - m_key_device_type(hw::device::type::type::SOFTWARE), + m_key_device_type(hw::device::type::SOFTWARE), m_ring_history_saved(false), m_ringdb(), m_last_block_reward(0), @@ -1159,6 +1162,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par command_line::add_arg(desc_params, opts.kdf_rounds); mms::message_store::init_options(desc_params); command_line::add_arg(desc_params, opts.hw_device); + command_line::add_arg(desc_params, opts.hw_device_address); command_line::add_arg(desc_params, opts.hw_device_derivation_path); command_line::add_arg(desc_params, opts.tx_notify); command_line::add_arg(desc_params, opts.offline); @@ -1376,6 +1380,7 @@ bool wallet2::reconnect_device() bool r = true; hw::device &hwdev = lookup_device(m_device_name); hwdev.set_name(m_device_name); + hwdev.set_address(m_device_address); hwdev.set_network_type(m_nettype); hwdev.set_derivation_path(m_device_derivation_path); hwdev.set_callback(get_device_callback()); @@ -4482,7 +4487,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st const cryptonote::account_keys& keys = m_account.get_keys(); hw::device &hwdev = m_account.get_device(); r = r && hwdev.verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key); - if (!m_watch_only && !m_multisig && hwdev.device_protocol() != hw::device::protocol::COLD)) + if (!m_watch_only && !m_multisig && hwdev.device_protocol() != hw::device::protocol::COLD) r = r && hwdev.verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_files_doesnt_correspond, m_keys_file, m_wallet_file); @@ -4506,7 +4511,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password) { // this temporary unlocking is necessary for Windows (otherwise the file couldn't be loaded). unlock_keys_file(); - bool r = verify_password(m_keys_file, password, m_account.get_device().device_protocol() == hw::device::protocol::COLD) || m_watch_only || m_multisig, m_account.get_device(), m_kdf_rounds); + bool r = verify_password(m_keys_file, password, m_account.get_device().device_protocol() == hw::device::protocol::COLD || m_watch_only || m_multisig, m_account.get_device(), m_kdf_rounds); lock_keys_file(); return r; } @@ -12019,7 +12024,7 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, s auto & hwdev = get_account().get_device(); // So far only Cold protocol devices are supported. - if (hwdev.device_protocol() != hw::device::protocol::COLD)) + if (hwdev.device_protocol() != hw::device::protocol::COLD) { return false; } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index b25290b2614..bb0eac05f82 100755 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1014,8 +1014,10 @@ namespace tools void track_uses(bool value) { m_track_uses = value; } std::chrono::seconds inactivity_lock_timeout() const { return m_inactivity_lock_timeout; } void inactivity_lock_timeout(std::chrono::seconds seconds) { m_inactivity_lock_timeout = seconds; } - const std::string & device_name() const { return m_device_name; } - void device_name(const std::string & device_name) { m_device_name = device_name; } + const std::string& device_name() const { return m_device_name; } + const std::string& device_address() const { return m_device_address; } + void device_name(std::string device_name) { m_device_name = std::move(device_name); } + void device_address(std::string device_address) { m_device_address = std::move(device_address); } const std::string & device_derivation_path() const { return m_device_derivation_path; } void device_derivation_path(const std::string &device_derivation_path) { m_device_derivation_path = device_derivation_path; } @@ -1644,6 +1646,7 @@ namespace tools std::unordered_set m_scanned_pool_txs[2]; size_t m_subaddress_lookahead_major, m_subaddress_lookahead_minor; std::string m_device_name; + std::string m_device_address; std::string m_device_derivation_path; uint64_t m_device_last_key_image_sync; bool m_offline;