diff --git a/src/cn_utils/crypto/crypto.cpp b/src/cn_utils/crypto/crypto.cpp index 13b8d210a..f5f8605d8 100644 --- a/src/cn_utils/crypto/crypto.cpp +++ b/src/cn_utils/crypto/crypto.cpp @@ -218,33 +218,6 @@ namespace crypto { return true; } - void crypto_ops::derive_secret_key(const key_derivation &derivation, size_t output_index, - const secret_key &base, secret_key &derived_key) { - ec_scalar scalar; - assert(sc_check(&base) == 0); - derivation_to_scalar(derivation, output_index, scalar); - sc_add(&unwrap(derived_key), &unwrap(base), &scalar); - } - - bool crypto_ops::derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &derived_key) { - ec_scalar scalar; - ge_p3 point1; - ge_p3 point2; - ge_cached point3; - ge_p1p1 point4; - ge_p2 point5; - if (ge_frombytes_vartime(&point1, &out_key) != 0) { - return false; - } - derivation_to_scalar(derivation, output_index, scalar); - ge_scalarmult_base(&point2, &scalar); - ge_p3_to_cached(&point3, &point2); - ge_sub(&point4, &point1, &point3); - ge_p1p1_to_p2(&point5, &point4); - ge_tobytes(&derived_key, &point5); - return true; - } - struct s_comm { hash h; ec_point key; diff --git a/src/cn_utils/crypto/crypto.h b/src/cn_utils/crypto/crypto.h index 380270970..2422830d7 100644 --- a/src/cn_utils/crypto/crypto.h +++ b/src/cn_utils/crypto/crypto.h @@ -124,10 +124,6 @@ namespace crypto { friend void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res); static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); - static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); - friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); - static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &); - friend bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &); static void generate_key_image(const public_key &, const secret_key &, key_image &); friend void generate_key_image(const public_key &, const secret_key &, key_image &); }; @@ -183,13 +179,6 @@ namespace crypto { inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) { return crypto_ops::derivation_to_scalar(derivation, output_index, res); } - inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index, - const secret_key &base, secret_key &derived_key) { - crypto_ops::derive_secret_key(derivation, output_index, base, derived_key); - } - inline bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result) { - return crypto_ops::derive_subaddress_public_key(out_key, derivation, output_index, result); - } /* To send money to a key: * * The sender generates an ephemeral key and includes it in transaction output. diff --git a/src/cn_utils/cryptonote_basic/cryptonote_format_utils.cpp b/src/cn_utils/cryptonote_basic/cryptonote_format_utils.cpp index a7bdb0395..13f128827 100644 --- a/src/cn_utils/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cn_utils/cryptonote_basic/cryptonote_format_utils.cpp @@ -215,92 +215,6 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool generate_key_image_helper(const account_keys& ack, const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev) - { - crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation); - bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation); - if (!r) - { - MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")"); - memcpy(&recv_derivation, rct::identity().bytes, sizeof(recv_derivation)); - } - - std::vector additional_recv_derivations; - for (size_t i = 0; i < additional_tx_public_keys.size(); ++i) - { - crypto::key_derivation additional_recv_derivation = AUTO_VAL_INIT(additional_recv_derivation); - r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation); - if (!r) - { - MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", " << ack.m_view_secret_key << ")"); - } - else - { - additional_recv_derivations.push_back(additional_recv_derivation); - } - } - - boost::optional subaddr_recv_info = is_out_to_acc_precomp(subaddresses, out_key, recv_derivation, additional_recv_derivations, real_output_index,hwdev); - CHECK_AND_ASSERT_MES(subaddr_recv_info, false, "key image helper: given output pubkey doesn't seem to belong to this address"); - - return generate_key_image_helper_precomp(ack, out_key, subaddr_recv_info->derivation, real_output_index, subaddr_recv_info->index, in_ephemeral, ki, hwdev); - } - //--------------------------------------------------------------- - bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev) - { - if (ack.m_spend_secret_key == crypto::null_skey) - { - // for watch-only wallet, simply copy the known output pubkey - in_ephemeral.pub = out_key; - in_ephemeral.sec = crypto::null_skey; - } - else - { - // derive secret key with subaddress - step 1: original CN derivation - crypto::secret_key scalar_step1; - hwdev.derive_secret_key(recv_derivation, real_output_index, ack.m_spend_secret_key, scalar_step1); // computes Hs(a*R || idx) + b - - // step 2: add Hs(a || index_major || index_minor) - crypto::secret_key subaddr_sk; - crypto::secret_key scalar_step2; - if (received_index.is_zero()) - { - scalar_step2 = scalar_step1; // treat index=(0,0) as a special case representing the main address - } - else - { - subaddr_sk = hwdev.get_subaddress_secret_key(ack.m_view_secret_key, received_index); - hwdev.sc_secret_add(scalar_step2, scalar_step1,subaddr_sk); - } - - in_ephemeral.sec = scalar_step2; - - if (ack.m_multisig_keys.empty()) - { - // when not in multisig, we know the full spend secret key, so the output pubkey can be obtained by scalarmultBase - CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive public key"); - } - else - { - // when in multisig, we only know the partial spend secret key. but we do know the full spend public key, so the output pubkey can be obtained by using the standard CN key derivation - CHECK_AND_ASSERT_MES(hwdev.derive_public_key(recv_derivation, real_output_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub), false, "Failed to derive public key"); - // and don't forget to add the contribution from the subaddress part - if (!received_index.is_zero()) - { - crypto::public_key subaddr_pk; - CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(subaddr_sk, subaddr_pk), false, "Failed to derive public key"); - add_public_key(in_ephemeral.pub, in_ephemeral.pub, subaddr_pk); - } - } - - CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key, - false, "key image helper precomp: given output pubkey doesn't match the derived one"); - } - - hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki); - return true; - } - //--------------------------------------------------------------- uint64_t power_integral(uint64_t a, uint64_t b) { if(b == 0) @@ -737,26 +651,6 @@ namespace cryptonote return false; } //--------------------------------------------------------------- - boost::optional is_out_to_acc_precomp(const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector& additional_derivations, size_t output_index, hw::device &hwdev) - { - // try the shared tx pubkey - crypto::public_key subaddress_spendkey; - hwdev.derive_subaddress_public_key(out_key, derivation, output_index, subaddress_spendkey); - auto found = subaddresses.find(subaddress_spendkey); - if (found != subaddresses.end()) - return subaddress_receive_info{ found->second, derivation }; - // try additional tx pubkeys if available - if (!additional_derivations.empty()) - { - CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations"); - hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey); - found = subaddresses.find(subaddress_spendkey); - if (found != subaddresses.end()) - return subaddress_receive_info{ found->second, additional_derivations[output_index] }; - } - return boost::none; - } - //--------------------------------------------------------------- bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered) { crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx); diff --git a/src/cn_utils/cryptonote_basic/cryptonote_format_utils.h b/src/cn_utils/cryptonote_basic/cryptonote_format_utils.h index b943edaee..e319607b3 100644 --- a/src/cn_utils/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cn_utils/cryptonote_basic/cryptonote_format_utils.h @@ -87,13 +87,10 @@ namespace cryptonote subaddress_index index; crypto::key_derivation derivation; }; - boost::optional is_out_to_acc_precomp(const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector& additional_derivations, size_t output_index, hw::device &hwdev); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, const std::vector& additional_tx_public_keys, std::vector& outs, uint64_t& money_transfered); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered); bool get_tx_fee(const transaction& tx, uint64_t & fee); uint64_t get_tx_fee(const transaction& tx); - bool generate_key_image_helper(const account_keys& ack, const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev); - bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev); void get_blob_hash(const blobdata& blob, crypto::hash& res); crypto::hash get_blob_hash(const blobdata& blob); std::string short_hash_str(const crypto::hash& h); diff --git a/src/cn_utils/device/device.hpp b/src/cn_utils/device/device.hpp index c0cdcd753..6ae775ffc 100644 --- a/src/cn_utils/device/device.hpp +++ b/src/cn_utils/device/device.hpp @@ -1,21 +1,21 @@ // Copyright (c) 2017-2018, The Monero Project -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. -// +// // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. -// +// // 3. Neither the name of the copyright holder nor the names of its contributors may be // used to endorse or promote products derived from this software without specific // prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL @@ -53,7 +53,7 @@ #define USE_DEVICE_LEDGER 1 #endif -#if !defined(HAVE_HIDAPI) +#if !defined(HAVE_HIDAPI) #undef USE_DEVICE_LEDGER #define USE_DEVICE_LEDGER 0 #endif @@ -123,7 +123,7 @@ namespace hw { /* ======================================================================= */ /* LOCKER */ - /* ======================================================================= */ + /* ======================================================================= */ virtual void lock(void) = 0; virtual void unlock(void) = 0; virtual bool try_lock(void) = 0; @@ -139,7 +139,6 @@ namespace hw { /* ======================================================================= */ /* SUB ADDRESS */ /* ======================================================================= */ - virtual bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) = 0; virtual crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) = 0; virtual std::vector get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) = 0; virtual cryptonote::account_public_address get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) = 0; @@ -156,7 +155,6 @@ namespace hw { virtual bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) = 0; virtual bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector &additional_derivations) = 0; virtual bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) = 0; - virtual bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) = 0; virtual bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) = 0; virtual bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) = 0; virtual bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) = 0; diff --git a/src/cn_utils/device/device_default.cpp b/src/cn_utils/device/device_default.cpp index c6cd7c06b..5d485a8bb 100644 --- a/src/cn_utils/device/device_default.cpp +++ b/src/cn_utils/device/device_default.cpp @@ -1,21 +1,21 @@ // Copyright (c) 2017-2018, The Monero Project -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. -// +// // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. -// +// // 3. Neither the name of the copyright holder nor the names of its contributors may be // used to endorse or promote products derived from this software without specific // prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL @@ -69,7 +69,7 @@ namespace hw { const std::string device_default::get_name() const { return this->name; } - + bool device_default::init(void) { dfns(); } @@ -90,8 +90,8 @@ namespace hw { /* ======================================================================= */ /* LOCKER */ - /* ======================================================================= */ - + /* ======================================================================= */ + void device_default::lock() { } bool device_default::try_lock() { return true; } @@ -122,10 +122,6 @@ namespace hw { /* SUB ADDRESS */ /* ======================================================================= */ - bool device_default::derive_subaddress_public_key(const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_key) { - return crypto::derive_subaddress_public_key(out_key, derivation, output_index,derived_key); - } - crypto::public_key device_default::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { if (index.is_zero()) return keys.m_account_address.m_spend_public_key; @@ -248,11 +244,6 @@ namespace hw { return true; } - bool device_default::derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &base, crypto::secret_key &derived_key){ - crypto::derive_secret_key(derivation, output_index, base, derived_key); - return true; - } - bool device_default::derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &base, crypto::public_key &derived_key){ return crypto::derive_public_key(derivation, output_index, base, derived_key); } diff --git a/src/cn_utils/device/device_default.hpp b/src/cn_utils/device/device_default.hpp index 04b9b4234..657e57d32 100644 --- a/src/cn_utils/device/device_default.hpp +++ b/src/cn_utils/device/device_default.hpp @@ -1,21 +1,21 @@ // Copyright (c) 2017-2018, The Monero Project -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. -// +// // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. -// +// // 3. Neither the name of the copyright holder nor the names of its contributors may be // used to endorse or promote products derived from this software without specific // prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL @@ -58,29 +58,28 @@ namespace hw { bool connect(void) override; bool disconnect() override; - + bool set_mode(device_mode mode) override; device_type get_type() const override {return device_type::SOFTWARE;}; /* ======================================================================= */ /* LOCKER */ - /* ======================================================================= */ + /* ======================================================================= */ void lock(void) override; void unlock(void) override; bool try_lock(void) override; - + /* ======================================================================= */ /* WALLET & ADDRESS */ /* ======================================================================= */ bool get_public_address(cryptonote::account_public_address &pubkey) override; bool get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) override; bool generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) override; - + /* ======================================================================= */ /* SUB ADDRESS */ /* ======================================================================= */ - bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) override; crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) override; std::vector get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) override; cryptonote::account_public_address get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) override; @@ -97,7 +96,6 @@ namespace hw { bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override; bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector &additional_derivations) override; bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override; - bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override; bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override; bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) override; bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) override; diff --git a/src/cn_utils/device/device_ledger.cpp b/src/cn_utils/device/device_ledger.cpp deleted file mode 100644 index f73b1d5a7..000000000 --- a/src/cn_utils/device/device_ledger.cpp +++ /dev/null @@ -1,1724 +0,0 @@ -// Copyright (c) 2017-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "device_ledger.hpp" -#include "log.hpp" -#include "ringct/rctOps.h" -#include "cryptonote_basic/account.h" -#include "cryptonote_basic/subaddress_index.h" -#include "cryptonote_core/cryptonote_tx_utils.h" - -#include -#include - -namespace hw { - - namespace ledger { - - #ifdef WITH_DEVICE_LEDGER - - #undef MONERO_DEFAULT_LOG_CATEGORY - #define MONERO_DEFAULT_LOG_CATEGORY "device.ledger" - - /* ===================================================================== */ - /* === Debug ==== */ - /* ===================================================================== */ - - void set_apdu_verbose(bool verbose) { - apdu_verbose = verbose; - } - - #define TRACKD MTRACE("hw") - #define ASSERT_SW(sw,ok,msk) CHECK_AND_ASSERT_THROW_MES(((sw)&(mask))==(ok), "Wrong Device Status : SW=" << std::hex << (sw) << " (EXPECT=" << std::hex << (ok) << ", MASK=" << std::hex << (mask) << ")") ; - #define ASSERT_T0(exp) CHECK_AND_ASSERT_THROW_MES(exp, "Protocol assert failure: "#exp ) ; - #define ASSERT_X(exp,msg) CHECK_AND_ASSERT_THROW_MES(exp, msg); - - #ifdef DEBUG_HWDEVICE - crypto::secret_key dbg_viewkey; - crypto::secret_key dbg_spendkey; - #endif - - /* ===================================================================== */ - /* === Keymap ==== */ - /* ===================================================================== */ - - ABPkeys::ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, const bool is_change, const bool need_additional_txkeys, const size_t real_output_index, const rct::key& P, const rct::key& AK) { - Aout = A; - Bout = B; - is_subaddress = is_subaddr; - is_change_address = is_change; - additional_key = need_additional_txkeys; - index = real_output_index; - Pout = P; - AKout = AK; - } - - ABPkeys::ABPkeys(const ABPkeys& keys) { - Aout = keys.Aout; - Bout = keys.Bout; - is_subaddress = keys.is_subaddress; - is_change_address = keys.is_change_address; - additional_key = keys.additional_key; - index = keys.index; - Pout = keys.Pout; - AKout = keys.AKout; - } - - bool Keymap::find(const rct::key& P, ABPkeys& keys) const { - size_t sz = ABP.size(); - for (size_t i=0; iid = device_id++; - this->reset_buffer(); - this->mode = NONE; - this->has_view_key = false; - MDEBUG( "Device "<id <<" Created"); - } - - device_ledger::~device_ledger() { - this->release(); - MDEBUG( "Device "<id <<" Destroyed"); - } - - /* ======================================================================= */ - /* LOCKER */ - /* ======================================================================= */ - - //automatic lock one more level on device ensuring the current thread is allowed to use it - #define AUTO_LOCK_CMD() \ - /* lock both mutexes without deadlock*/ \ - boost::lock(device_locker, command_locker); \ - /* make sure both already-locked mutexes are unlocked at the end of scope */ \ - boost::lock_guard lock1(device_locker, boost::adopt_lock); \ - boost::lock_guard lock2(command_locker, boost::adopt_lock) - - //lock the device for a long sequence - void device_ledger::lock(void) { - MDEBUG( "Ask for LOCKING for device "<name << " in thread "); - device_locker.lock(); - MDEBUG( "Device "<name << " LOCKed"); - } - - //lock the device for a long sequence - bool device_ledger::try_lock(void) { - MDEBUG( "Ask for LOCKING(try) for device "<name << " in thread "); - bool r = device_locker.try_lock(); - if (r) { - MDEBUG( "Device "<name << " LOCKed(try)"); - } else { - MDEBUG( "Device "<name << " not LOCKed(try)"); - } - return r; - } - - //lock the device for a long sequence - void device_ledger::unlock(void) { - try { - MDEBUG( "Ask for UNLOCKING for device "<name << " in thread "); - } catch (...) { - } - device_locker.unlock(); - MDEBUG( "Device "<name << " UNLOCKed"); - } - - - /* ======================================================================= */ - /* IO */ - /* ======================================================================= */ - - void device_ledger::logCMD() { - if (apdu_verbose) { - char strbuffer[1024]; - snprintf(strbuffer, sizeof(strbuffer), "%.02x %.02x %.02x %.02x %.02x ", - this->buffer_send[0], - this->buffer_send[1], - this->buffer_send[2], - this->buffer_send[3], - this->buffer_send[4] - ); - const size_t len = strlen(strbuffer); - buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_send+5), this->length_send-5); - MDEBUG( "CMD : " << strbuffer); - } - } - - void device_ledger::logRESP() { - if (apdu_verbose) { - char strbuffer[1024]; - snprintf(strbuffer, sizeof(strbuffer), "%.04x ", this->sw); - const size_t len = strlen(strbuffer); - buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_recv), this->length_recv); - MDEBUG( "RESP : " << strbuffer); - - } - } - - int device_ledger::set_command_header(unsigned char ins, unsigned char p1, unsigned char p2) { - reset_buffer(); - int offset = 0; - this->buffer_send[0] = PROTOCOL_VERSION; - this->buffer_send[1] = ins; - this->buffer_send[2] = p1; - this->buffer_send[3] = p2; - this->buffer_send[4] = 0x00; - return 5; - } - - int device_ledger::set_command_header_noopt(unsigned char ins, unsigned char p1, unsigned char p2) { - int offset = set_command_header(ins, p1, p2); - //options - this->buffer_send[offset++] = 0; - this->buffer_send[4] = offset - 5; - return offset; - } - - void device_ledger::send_simple(unsigned char ins, unsigned char p1) { - this->length_send = set_command_header_noopt(ins, p1); - this->exchange(); - } - - bool device_ledger::reset() { - send_simple(INS_RESET); - return true; - } - - unsigned int device_ledger::exchange(unsigned int ok, unsigned int mask) { - logCMD(); - - this->length_recv = hw_device.exchange(this->buffer_send, this->length_send, this->buffer_recv, BUFFER_SEND_SIZE); - ASSERT_X(this->length_recv>=2, "Communication error, less than tow bytes received"); - - this->length_recv -= 2; - this->sw = (this->buffer_recv[length_recv]<<8) | this->buffer_recv[length_recv+1]; - ASSERT_SW(this->sw,ok,msk); - - logRESP(); - return this->sw; - } - - void device_ledger::reset_buffer() { - this->length_send = 0; - memset(this->buffer_send, 0, BUFFER_SEND_SIZE); - this->length_recv = 0; - memset(this->buffer_recv, 0, BUFFER_RECV_SIZE); - } - - /* ======================================================================= */ - /* SETUP/TEARDOWN */ - /* ======================================================================= */ - - bool device_ledger::set_name(const std::string & name) { - this->name = name; - return true; - } - - const std::string device_ledger::get_name() const { - if (this->full_name.empty() || !this->connected()) { - return std::string("name).append(">"); - } - return this->name; - } - - bool device_ledger::init(void) { - #ifdef DEBUG_HWDEVICE - this->controle_device = &hw::get_device("default"); - #endif - this->release(); - hw_device.init(); - MDEBUG( "Device "<id <<" HIDUSB inited"); - return true; - } - - bool device_ledger::connect(void) { - this->disconnect(); - hw_device.connect(0x2c97,0x0001, 0, 0xffa0, hw_device.OR_SELECT); - this->reset(); - #ifdef DEBUG_HWDEVICE - cryptonote::account_public_address pubkey; - this->get_public_address(pubkey); - #endif - crypto::secret_key vkey; - crypto::secret_key skey; - this->get_secret_keys(vkey,skey); - - return true; - } - - bool device_ledger::connected(void) const { - return hw_device.connected(); - } - - bool device_ledger::disconnect() { - hw_device.disconnect(); - return true; - } - - bool device_ledger::release() { - this->disconnect(); - hw_device.release(); - return true; - } - - bool device_ledger::set_mode(device_mode mode) { - AUTO_LOCK_CMD(); - - int offset; - - switch(mode) { - case TRANSACTION_CREATE_REAL: - case TRANSACTION_CREATE_FAKE: - offset = set_command_header_noopt(INS_SET_SIGNATURE_MODE, 1); - //account - this->buffer_send[offset] = mode; - offset += 1; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - this->mode = mode; - break; - - case TRANSACTION_PARSE: - case NONE: - this->mode = mode; - break; - default: - CHECK_AND_ASSERT_THROW_MES(false, " device_ledger::set_mode(unsigned int mode): invalid mode: "<buffer_recv, 32); - memmove(pubkey.m_spend_public_key.data, this->buffer_recv+32, 32); - - return true; - } - - bool device_ledger::get_secret_keys(crypto::secret_key &vkey , crypto::secret_key &skey) { - AUTO_LOCK_CMD(); - - //secret key are represented as fake key on the wallet side - memset(vkey.data, 0x00, 32); - memset(skey.data, 0xFF, 32); - - //spcialkey, normal conf handled in decrypt - send_simple(INS_GET_KEY, 0x02); - - //View key is retrievied, if allowed, to speed up blockchain parsing - memmove(this->viewkey.data, this->buffer_recv+0, 32); - if (is_fake_view_key(this->viewkey)) { - MDEBUG("Have Not view key"); - this->has_view_key = false; - } else { - MDEBUG("Have view key"); - this->has_view_key = true; - } - - #ifdef DEBUG_HWDEVICE - memmove(dbg_viewkey.data, this->buffer_recv+0, 32); - memmove(dbg_spendkey.data, this->buffer_recv+32, 32); - #endif - - return true; - } - - bool device_ledger::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - crypto::chacha_key key_x; - cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); - this->controle_device->generate_chacha_key(keys_x, key_x, kdf_rounds); - #endif - - send_simple(INS_GET_CHACHA8_PREKEY); - - char prekey[200]; - memmove(prekey, &this->buffer_recv[0], 200); - crypto::generate_chacha_key_prehashed(&prekey[0], sizeof(prekey), key, kdf_rounds); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("generate_chacha_key_prehashed", "key", (char*)key_x.data(), (char*)key.data()); - #endif - - return true; - } - - /* ======================================================================= */ - /* SUB ADDRESS */ - /* ======================================================================= */ - - bool device_ledger::derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub){ - AUTO_LOCK_CMD(); - #ifdef DEBUG_HWDEVICE - const crypto::public_key pub_x = pub; - crypto::key_derivation derivation_x; - if ((this->mode == TRANSACTION_PARSE) && has_view_key) { - derivation_x = derivation; - } else { - derivation_x = hw::ledger::decrypt(derivation); - } - const std::size_t output_index_x = output_index; - crypto::public_key derived_pub_x; - log_hexbuffer("derive_subaddress_public_key: [[IN]] pub ", pub_x.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((int)output_index_x)); - this->controle_device->derive_subaddress_public_key(pub_x, derivation_x,output_index_x,derived_pub_x); - log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32); - #endif - - if ((this->mode == TRANSACTION_PARSE) && has_view_key) { - //If we are in TRANSACTION_PARSE, the given derivation has been retrieved uncrypted (wihtout the help - //of the device), so continue that way. - MDEBUG( "derive_subaddress_public_key : PARSE mode with known viewkey"); - crypto::derive_subaddress_public_key(pub, derivation, output_index,derived_pub); - } else { - - int offset = set_command_header_noopt(INS_DERIVE_SUBADDRESS_PUBLIC_KEY); - //pub - memmove(this->buffer_send+offset, pub.data, 32); - offset += 32; - //derivation - memmove(this->buffer_send+offset, derivation.data, 32); - offset += 32; - //index - this->buffer_send[offset+0] = output_index>>24; - this->buffer_send[offset+1] = output_index>>16; - this->buffer_send[offset+2] = output_index>>8; - this->buffer_send[offset+3] = output_index>>0; - offset += 4; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //pub key - memmove(derived_pub.data, &this->buffer_recv[0], 32); - } - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); - #endif - - return true; - } - - crypto::public_key device_ledger::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { - AUTO_LOCK_CMD(); - crypto::public_key D; - - #ifdef DEBUG_HWDEVICE - const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); - const cryptonote::subaddress_index index_x = index; - crypto::public_key D_x; - 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_x.major)+"."+std::to_string(index_x.minor)); - D_x = this->controle_device->get_subaddress_spend_public_key(keys_x, index_x); - log_hexbuffer("get_subaddress_spend_public_key: [[OUT]] derivation ", D_x.data, 32); - #endif - - if (index.is_zero()) { - D = keys.m_account_address.m_spend_public_key; - } else { - - int offset = set_command_header_noopt(INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY); - //index - static_assert(sizeof(cryptonote::subaddress_index) == 8, "cryptonote::subaddress_index shall be 8 bytes length"); - memmove(this->buffer_send+offset, &index, sizeof(cryptonote::subaddress_index)); - offset +=8 ; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - memmove(D.data, &this->buffer_recv[0], 32); - } - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("get_subaddress_spend_public_key", "D", D_x.data, D.data); - #endif - - return D; - } - - std::vector device_ledger::get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) { - std::vector pkeys; - cryptonote::subaddress_index index = {account, begin}; - crypto::public_key D; - for (uint32_t idx = begin; idx < end; ++idx) { - index.minor = idx; - D = this->get_subaddress_spend_public_key(keys, index); - pkeys.push_back(D); - } - return pkeys; - } - - cryptonote::account_public_address device_ledger::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { - AUTO_LOCK_CMD(); - cryptonote::account_public_address address; - - #ifdef DEBUG_HWDEVICE - const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); - const cryptonote::subaddress_index index_x = index; - cryptonote::account_public_address address_x; - 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_view_secret_key ", keys_x.m_view_secret_key.data, 32); - log_hexbuffer("get_subaddress: [[IN]] keys.m_spend_public_key", keys_x.m_account_address.m_spend_public_key.data, 32); - log_message ("get_subaddress: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor)); - address_x = this->controle_device->get_subaddress(keys_x, index_x); - log_hexbuffer("get_subaddress: [[OUT]] keys.m_view_public_key ", address_x.m_view_public_key.data, 32); - log_hexbuffer("get_subaddress: [[OUT]] keys.m_spend_public_key", address_x.m_spend_public_key.data, 32); - #endif - - if (index.is_zero()) { - address = keys.m_account_address; - } else { - int offset = set_command_header_noopt(INS_GET_SUBADDRESS); - //index - static_assert(sizeof(cryptonote::subaddress_index) == 8, "cryptonote::subaddress_index shall be 8 bytes length"); - memmove(this->buffer_send+offset, &index, sizeof(cryptonote::subaddress_index)); - offset +=8 ; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - memmove(address.m_view_public_key.data, &this->buffer_recv[0], 32); - memmove(address.m_spend_public_key.data, &this->buffer_recv[32], 32); - } - - #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); - #endif - - return address; - } - - crypto::secret_key device_ledger::get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) { - AUTO_LOCK_CMD(); - crypto::secret_key sub_sec; - - #ifdef DEBUG_HWDEVICE - const crypto::secret_key sec_x = hw::ledger::decrypt(sec); - const cryptonote::subaddress_index index_x = index; - crypto::secret_key sub_sec_x; - 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); - sub_sec_x = this->controle_device->get_subaddress_secret_key(sec_x, index_x); - log_hexbuffer("get_subaddress_secret_key: [[OUT]] sub_sec", sub_sec_x.data, 32); - #endif - - int offset = set_command_header_noopt(INS_GET_SUBADDRESS_SECRET_KEY); - //sec - memmove(this->buffer_send+offset, sec.data, 32); - offset += 32; - //index - static_assert(sizeof(cryptonote::subaddress_index) == 8, "cryptonote::subaddress_index shall be 8 bytes length"); - memmove(this->buffer_send+offset, &index, sizeof(cryptonote::subaddress_index)); - offset +=8 ; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - memmove(sub_sec.data, &this->buffer_recv[0], 32); - - #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); - #endif - - return sub_sec; - } - - /* ======================================================================= */ - /* DERIVATION & KEY */ - /* ======================================================================= */ - - bool device_ledger::verify_keys(const crypto::secret_key &secret_key, const crypto::public_key &public_key) { - AUTO_LOCK_CMD(); - int offset, sw; - - offset = set_command_header_noopt(INS_VERIFY_KEY); - //sec - memmove(this->buffer_send+offset, secret_key.data, 32); - offset += 32; - //pub - memmove(this->buffer_send+offset, public_key.data, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - uint32_t verified = - this->buffer_recv[0] << 24 | - this->buffer_recv[1] << 16 | - this->buffer_recv[2] << 8 | - this->buffer_recv[3] << 0 ; - - return verified == 1; - } - - bool device_ledger::scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const rct::key P_x = P; - const rct::key a_x = hw::ledger::decrypt(a); - rct::key aP_x; - log_hexbuffer("scalarmultKey: [[IN]] P ", (char*)P_x.bytes, 32); - log_hexbuffer("scalarmultKey: [[IN]] a ", (char*)a_x.bytes, 32); - this->controle_device->scalarmultKey(aP_x, P_x, a_x); - log_hexbuffer("scalarmultKey: [[OUT]] aP", (char*)aP_x.bytes, 32); - #endif - - int offset = set_command_header_noopt(INS_SECRET_SCAL_MUL_KEY); - //pub - memmove(this->buffer_send+offset, P.bytes, 32); - offset += 32; - //sec - memmove(this->buffer_send+offset, a.bytes, 32); - offset += 32; - - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //pub key - memmove(aP.bytes, &this->buffer_recv[0], 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("scalarmultKey", "mulkey", (char*)aP_x.bytes, (char*)aP.bytes); - #endif - - return true; - } - - bool device_ledger::scalarmultBase(rct::key &aG, const rct::key &a) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const rct::key a_x = hw::ledger::decrypt(a); - rct::key aG_x; - log_hexbuffer("scalarmultKey: [[IN]] a ", (char*)a_x.bytes, 32); - this->controle_device->scalarmultBase(aG_x, a_x); - log_hexbuffer("scalarmultKey: [[OUT]] aG", (char*)aG_x.bytes, 32); - #endif - - int offset = set_command_header_noopt(INS_SECRET_SCAL_MUL_BASE); - //sec - memmove(this->buffer_send+offset, a.bytes, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //pub key - memmove(aG.bytes, &this->buffer_recv[0], 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("scalarmultBase", "mulkey", (char*)aG_x.bytes, (char*)aG.bytes); - #endif - - return true; - } - - bool device_ledger::sc_secret_add( crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const crypto::secret_key a_x = hw::ledger::decrypt(a); - const crypto::secret_key b_x = hw::ledger::decrypt(b); - crypto::secret_key r_x; - this->controle_device->sc_secret_add(r_x, a_x, b_x); - #endif - - int offset = set_command_header_noopt(INS_SECRET_KEY_ADD); - //sec key - memmove(this->buffer_send+offset, a.data, 32); - offset += 32; - //sec key - memmove(this->buffer_send+offset, b.data, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //pub key - memmove(r.data, &this->buffer_recv[0], 32); - - #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); - #endif - - return true; - } - - crypto::secret_key device_ledger::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover) { - AUTO_LOCK_CMD(); - if (recover) { - throw std::runtime_error("device generate key does not support recover"); - } - - #ifdef DEBUG_HWDEVICE - bool recover_x = recover; - const crypto::secret_key recovery_key_x = recovery_key; - crypto::public_key pub_x; - crypto::secret_key sec_x; - #endif - - send_simple(INS_GENERATE_KEYPAIR); - - //pub key - memmove(pub.data, &this->buffer_recv[0], 32); - memmove(sec.data, &this->buffer_recv[32], 32); - - #ifdef DEBUG_HWDEVICE - crypto::secret_key sec_clear = hw::ledger::decrypt(sec); - sec_x = sec_clear; - crypto::secret_key_to_public_key(sec_x,pub_x); - hw::ledger::check32("generate_keys", "pub", pub_x.data, pub.data); - #endif - - return sec; - - } - - bool device_ledger::generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) { - AUTO_LOCK_CMD(); - bool r = false; - - #ifdef DEBUG_HWDEVICE - const crypto::public_key pub_x = pub; - const crypto::secret_key sec_x = hw::ledger::decrypt(sec); - crypto::key_derivation derivation_x; - log_hexbuffer("generate_key_derivation: [[IN]] pub ", pub_x.data, 32); - log_hexbuffer("generate_key_derivation: [[IN]] sec ", sec_x.data, 32); - this->controle_device->generate_key_derivation(pub_x, sec_x, derivation_x); - log_hexbuffer("generate_key_derivation: [[OUT]] derivation", derivation_x.data, 32); - #endif - - if ((this->mode == TRANSACTION_PARSE) && has_view_key) { - //A derivation is resquested in PASRE mode and we have the view key, - //so do that wihtout the device and return the derivation unencrypted. - MDEBUG( "generate_key_derivation : PARSE mode with known viewkey"); - //Note derivation in PARSE mode can only happen with viewkey, so assert it! - assert(is_fake_view_key(sec)); - r = crypto::generate_key_derivation(pub, this->viewkey, derivation); - } else { - - int offset = set_command_header_noopt(INS_GEN_KEY_DERIVATION); - //pub - memmove(this->buffer_send+offset, pub.data, 32); - offset += 32; - //sec - memmove(this->buffer_send+offset, sec.data, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //derivattion data - memmove(derivation.data, &this->buffer_recv[0], 32); - r = true; - } - #ifdef DEBUG_HWDEVICE - crypto::key_derivation derivation_clear ; - if ((this->mode == TRANSACTION_PARSE) && has_view_key) { - derivation_clear = derivation; - }else { - derivation_clear = hw::ledger::decrypt(derivation); - } - hw::ledger::check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data); - #endif - - return r; - } - - bool device_ledger::conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector &additional_derivations) { - const crypto::public_key *pkey=NULL; - if (derivation == main_derivation) { - pkey = &tx_pub_key; - MDEBUG("conceal derivation with main tx pub key"); - } else { - for(size_t n=0; n < additional_derivations.size();++n) { - if(derivation == additional_derivations[n]) { - pkey = &additional_tx_pub_keys[n]; - MDEBUG("conceal derivation with additionnal tx pub key"); - break; - } - } - } - ASSERT_X(pkey, "Mismatched derivation on scan info"); - return this->generate_key_derivation(*pkey, crypto::null_skey, derivation); - } - - bool device_ledger::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); - const size_t output_index_x = output_index; - crypto::ec_scalar res_x; - log_hexbuffer("derivation_to_scalar: [[IN]] derivation ", derivation_x.data, 32); - log_message ("derivation_to_scalar: [[IN]] output_index ", std::to_string(output_index_x)); - this->controle_device->derivation_to_scalar(derivation_x, output_index_x, res_x); - log_hexbuffer("derivation_to_scalar: [[OUT]] res ", res_x.data, 32); - #endif - - int offset = set_command_header_noopt(INS_DERIVATION_TO_SCALAR); - //derivattion - memmove(this->buffer_send+offset, derivation.data, 32); - offset += 32; - //index - this->buffer_send[offset+0] = output_index>>24; - this->buffer_send[offset+1] = output_index>>16; - this->buffer_send[offset+2] = output_index>>8; - this->buffer_send[offset+3] = output_index>>0; - offset += 4; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //derivattion data - memmove(res.data, &this->buffer_recv[0], 32); - - #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); - #endif - - return true; - } - - bool device_ledger::derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); - const std::size_t output_index_x = output_index; - const crypto::secret_key sec_x = hw::ledger::decrypt(sec); - crypto::secret_key derived_sec_x; - log_hexbuffer("derive_secret_key: [[IN]] derivation ", derivation_x.data, 32); - log_message ("derive_secret_key: [[IN]] index ", std::to_string(output_index_x)); - log_hexbuffer("derive_secret_key: [[IN]] sec ", sec_x.data, 32); - this->controle_device->derive_secret_key(derivation_x, output_index_x, sec_x, derived_sec_x); - log_hexbuffer("derive_secret_key: [[OUT]] derived_sec", derived_sec_x.data, 32); - #endif - - int offset = set_command_header_noopt(INS_DERIVE_SECRET_KEY); - //derivation - memmove(this->buffer_send+offset, derivation.data, 32); - offset += 32; - //index - this->buffer_send[offset+0] = output_index>>24; - this->buffer_send[offset+1] = output_index>>16; - this->buffer_send[offset+2] = output_index>>8; - this->buffer_send[offset+3] = output_index>>0; - offset += 4; - //sec - memmove(this->buffer_send+offset, sec.data, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //pub key - memmove(derived_sec.data, &this->buffer_recv[0], 32); - - #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); - #endif - - return true; - } - - bool device_ledger::derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub){ - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); - const std::size_t output_index_x = output_index; - const crypto::public_key pub_x = pub; - crypto::public_key derived_pub_x; - log_hexbuffer("derive_public_key: [[IN]] derivation ", derivation_x.data, 32); - log_message ("derive_public_key: [[IN]] output_index", std::to_string(output_index_x)); - log_hexbuffer("derive_public_key: [[IN]] pub ", pub_x.data, 32); - this->controle_device->derive_public_key(derivation_x, output_index_x, pub_x, derived_pub_x); - log_hexbuffer("derive_public_key: [[OUT]] derived_pub ", derived_pub_x.data, 32); - #endif - - int offset = set_command_header_noopt(INS_DERIVE_PUBLIC_KEY); - //derivation - memmove(this->buffer_send+offset, derivation.data, 32); - offset += 32; - //index - this->buffer_send[offset+0] = output_index>>24; - this->buffer_send[offset+1] = output_index>>16; - this->buffer_send[offset+2] = output_index>>8; - this->buffer_send[offset+3] = output_index>>0; - offset += 4; - //pub - memmove(this->buffer_send+offset, pub.data, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //pub key - memmove(derived_pub.data, &this->buffer_recv[0], 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("derive_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); - #endif - - return true; - } - - bool device_ledger::secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const crypto::secret_key sec_x = hw::ledger::decrypt(sec); - crypto::public_key pub_x; - log_hexbuffer("secret_key_to_public_key: [[IN]] sec ", sec_x.data, 32); - bool rc = this->controle_device->secret_key_to_public_key(sec_x, pub_x); - log_hexbuffer("secret_key_to_public_key: [[OUT]] pub", pub_x.data, 32); - if (!rc){ - log_message("secret_key_to_public_key", "secret_key rejected"); - } - #endif - - int offset = set_command_header_noopt(INS_SECRET_KEY_TO_PUBLIC_KEY); - //sec key - memmove(this->buffer_send+offset, sec.data, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //pub key - memmove(pub.data, &this->buffer_recv[0], 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("secret_key_to_public_key", "pub", pub_x.data, pub.data); - #endif - - return true; - } - - bool device_ledger::generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image){ - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const crypto::public_key pub_x = pub; - const crypto::secret_key sec_x = hw::ledger::decrypt(sec); - crypto::key_image image_x; - log_hexbuffer("generate_key_image: [[IN]] pub ", pub_x.data, 32); - log_hexbuffer("generate_key_image: [[IN]] sec ", sec_x.data, 32); - this->controle_device->generate_key_image(pub_x, sec_x, image_x); - log_hexbuffer("generate_key_image: [[OUT]] image ", image_x.data, 32); - #endif - - int offset = set_command_header_noopt(INS_GEN_KEY_IMAGE); - //pub - memmove(this->buffer_send+offset, pub.data, 32); - offset += 32; - //sec - memmove(this->buffer_send+offset, sec.data, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //pub key - memmove(image.data, &this->buffer_recv[0], 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("generate_key_image", "image", image_x.data, image.data); - #endif - - return true; - } - - /* ======================================================================= */ - /* TRANSACTION */ - /* ======================================================================= */ - - bool device_ledger::open_tx(crypto::secret_key &tx_key) { - AUTO_LOCK_CMD(); - - key_map.clear(); - int offset = set_command_header_noopt(INS_OPEN_TX, 0x01); - - //account - this->buffer_send[offset+0] = 0x00; - this->buffer_send[offset+1] = 0x00; - this->buffer_send[offset+2] = 0x00; - this->buffer_send[offset+3] = 0x00; - offset += 4; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - memmove(tx_key.data, &this->buffer_recv[32], 32); - - return true; - } - - bool device_ledger::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const crypto::public_key public_key_x = public_key; - const crypto::secret_key secret_key_x = hw::ledger::decrypt(secret_key); - crypto::hash8 payment_id_x = payment_id; - this->controle_device->encrypt_payment_id(payment_id_x, public_key_x, secret_key_x); - #endif - - int offset = set_command_header_noopt(INS_STEALTH); - //pub - memmove(&this->buffer_send[offset], public_key.data, 32); - offset += 32; - //sec - memmove(&this->buffer_send[offset], secret_key.data, 32); - offset += 32; - //id - memmove(&this->buffer_send[offset], payment_id.data, 8); - offset += 8; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - memmove(payment_id.data, &this->buffer_recv[0], 8); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check8("stealth", "payment_id", payment_id_x.data, payment_id.data); - #endif - - return true; - } - - - bool device_ledger::generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key, - const cryptonote::tx_destination_entry &dst_entr, const boost::optional &change_addr, const size_t output_index, - const bool &need_additional_txkeys, const std::vector &additional_tx_keys, - std::vector &additional_tx_public_keys, - std::vector &amount_keys, - crypto::public_key &out_eph_public_key) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const size_t &tx_version_x = tx_version; - const cryptonote::account_keys sender_account_keys_x = sender_account_keys; - memmove((void*)sender_account_keys_x.m_view_secret_key.data, dbg_viewkey.data, 32); - - const crypto::public_key &txkey_pub_x = txkey_pub; - const crypto::secret_key &tx_key_x = tx_key; - const cryptonote::tx_destination_entry &dst_entr_x = dst_entr; - const boost::optional &change_addr_x = change_addr; - const size_t &output_index_x = output_index; - const bool &need_additional_txkeys_x = need_additional_txkeys; - const std::vector &additional_tx_keys_x = additional_tx_keys; - std::vector additional_tx_public_keys_x; - std::vector amount_keys_x; - crypto::public_key out_eph_public_key_x; - this->controle_device->generate_output_ephemeral_keys(tx_version_x, sender_account_keys_x, txkey_pub_x, tx_key_x, dst_entr_x, change_addr_x, output_index_x, need_additional_txkeys_x, additional_tx_keys_x, - additional_tx_public_keys_x, amount_keys_x, out_eph_public_key_x); - #endif - - // make additional tx pubkey if necessary - cryptonote::keypair additional_txkey; - if (need_additional_txkeys) { - additional_txkey.sec = additional_tx_keys[output_index]; - } - - //compute derivation, out_eph_public_key, and amount key in one shot on device, to ensure checkable link - const crypto::secret_key *sec; - bool is_change; - - if (change_addr && dst_entr.addr == *change_addr) - { - // sending change to yourself; derivation = a*R - is_change = true; - sec = &sender_account_keys.m_view_secret_key; - } - else - { - is_change = false; - if (dst_entr.is_subaddress && need_additional_txkeys) { - sec = &additional_txkey.sec; - } else { - sec = &tx_key; - } - } - - int offset = set_command_header_noopt(INS_GEN_TXOUT_KEYS); - //tx_version - this->buffer_send[offset+0] = tx_version>>24; - this->buffer_send[offset+1] = tx_version>>16; - this->buffer_send[offset+2] = tx_version>>8; - this->buffer_send[offset+3] = tx_version>>0; - offset += 4; - //tx_sec - memmove(&this->buffer_send[offset], sec->data, 32); - offset += 32; - //Aout - memmove(&this->buffer_send[offset], dst_entr.addr.m_view_public_key.data, 32); - offset += 32; - //Bout - memmove(&this->buffer_send[offset], dst_entr.addr.m_spend_public_key.data, 32); - offset += 32; - //output index - this->buffer_send[offset+0] = output_index>>24; - this->buffer_send[offset+1] = output_index>>16; - this->buffer_send[offset+2] = output_index>>8; - this->buffer_send[offset+3] = output_index>>0; - offset += 4; - //is_change, - this->buffer_send[offset] = is_change; - offset++; - //is_subaddress - this->buffer_send[offset] = dst_entr.is_subaddress; - offset++; - //need_additional_key - this->buffer_send[offset] = need_additional_txkeys; - offset++; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - offset = 0; - unsigned int recv_len = this->length_recv; - if (need_additional_txkeys) - { - ASSERT_X(recv_len>=32, "Not enought data from device"); - memmove(additional_txkey.pub.data, &this->buffer_recv[offset], 32); - additional_tx_public_keys.push_back(additional_txkey.pub); - offset += 32; - recv_len -= 32; - } - if (tx_version > 1) - { - ASSERT_X(recv_len>=32, "Not enought data from device"); - crypto::secret_key scalar1; - memmove(scalar1.data, &this->buffer_recv[offset],32); - amount_keys.push_back(rct::sk2rct(scalar1)); - offset += 32; - recv_len -= 32; - } - ASSERT_X(recv_len>=32, "Not enought data from device"); - memmove(out_eph_public_key.data, &this->buffer_recv[offset], 32); - recv_len -= 32; - - // add ABPkeys - this->add_output_key_mapping(dst_entr.addr.m_view_public_key, dst_entr.addr.m_spend_public_key, dst_entr.is_subaddress, is_change, - need_additional_txkeys, output_index, - amount_keys.back(), out_eph_public_key); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("generate_output_ephemeral_keys", "amount_key", (const char*)amount_keys_x.back().bytes, (const char*)hw::ledger::decrypt(amount_keys.back()).bytes); - if (need_additional_txkeys) { - hw::ledger::check32("generate_output_ephemeral_keys", "additional_tx_key", additional_tx_keys_x.back().data, additional_tx_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); - #endif - - return true; - } - - bool device_ledger::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const bool is_change, - const bool need_additional, const size_t real_output_index, - const rct::key &amount_key, const crypto::public_key &out_eph_public_key) { - key_map.add(ABPkeys(rct::pk2rct(Aout),rct::pk2rct(Bout), is_subaddress, is_change, need_additional, real_output_index, rct::pk2rct(out_eph_public_key), amount_key)); - return true; - } - - bool device_ledger::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & AKout, bool short_amount) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const rct::key AKout_x = hw::ledger::decrypt(AKout); - rct::ecdhTuple unmasked_x = unmasked; - this->controle_device->ecdhEncode(unmasked_x, AKout_x, short_amount); - #endif - - int offset = set_command_header(INS_BLIND); - //options - this->buffer_send[offset] = short_amount?0x02:0x00; - offset += 1; - // AKout - memmove(this->buffer_send+offset, AKout.bytes, 32); - offset += 32; - //mask k - memmove(this->buffer_send+offset, unmasked.mask.bytes, 32); - offset += 32; - //value v - memmove(this->buffer_send+offset, unmasked.amount.bytes, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - memmove(unmasked.amount.bytes, &this->buffer_recv[0], 32); - memmove(unmasked.mask.bytes, &this->buffer_recv[32], 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("ecdhEncode", "amount", (char*)unmasked_x.amount.bytes, (char*)unmasked.amount.bytes); - hw::ledger::check32("ecdhEncode", "mask", (char*)unmasked_x.mask.bytes, (char*)unmasked.mask.bytes); - - log_hexbuffer("Blind AKV input", (char*)&this->buffer_recv[64], 3*32); - #endif - - return true; - } - - bool device_ledger::ecdhDecode(rct::ecdhTuple & masked, const rct::key & AKout, bool short_amount) { - AUTO_LOCK_CMD(); - - #ifdef DEBUG_HWDEVICE - const rct::key AKout_x = hw::ledger::decrypt(AKout); - rct::ecdhTuple masked_x = masked; - this->controle_device->ecdhDecode(masked_x, AKout_x, short_amount); - #endif - - int offset = set_command_header(INS_UNBLIND); - //options - this->buffer_send[offset] = short_amount?0x02:0x00; - offset += 1; - // AKout - memmove(this->buffer_send+offset, AKout.bytes, 32); - offset += 32; - //mask k - memmove(this->buffer_send+offset, masked.mask.bytes, 32); - offset += 32; - //value v - memmove(this->buffer_send+offset, masked.amount.bytes, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - memmove(masked.amount.bytes, &this->buffer_recv[0], 32); - memmove(masked.mask.bytes, &this->buffer_recv[32], 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("ecdhDecode", "amount", (char*)masked_x.amount.bytes, (char*)masked.amount.bytes); - hw::ledger::check32("ecdhDecode", "mask", (char*)masked_x.mask.bytes,(char*) masked.mask.bytes); - #endif - - return true; - } - - bool device_ledger::mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, - const rct::keyV &hashes, const rct::ctkeyV &outPk, - rct::key &prehash) { - AUTO_LOCK_CMD(); - unsigned int data_offset, C_offset, kv_offset, i; - const char *data; - - #ifdef DEBUG_HWDEVICE - const std::string blob_x = blob; - size_t inputs_size_x = inputs_size; - size_t outputs_size_x = outputs_size; - const rct::keyV hashes_x = hashes; - const rct::ctkeyV outPk_x = outPk; - rct::key prehash_x; - this->controle_device->mlsag_prehash(blob_x, inputs_size_x, outputs_size_x, hashes_x, outPk_x, prehash_x); - if (inputs_size) { - log_message("mlsag_prehash", (std::string("inputs_size not null: ") + std::to_string(inputs_size)).c_str()); - } - this->key_map.log(); - #endif - - data = blob.data(); - - // ====== u8 type, varint txnfee ====== - int offset = set_command_header(INS_VALIDATE, 0x01, 0x01); - //options - this->buffer_send[offset] = (inputs_size == 0)?0x00:0x80; - offset += 1; - - //type - uint8_t type = data[0]; - this->buffer_send[offset] = data[0]; - offset += 1; - - //txnfee - data_offset = 1; - while (data[data_offset]&0x80) { - this->buffer_send[offset] = data[data_offset]; - offset += 1; - data_offset += 1; - } - this->buffer_send[offset] = data[data_offset]; - offset += 1; - data_offset += 1; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //pseudoOuts - if (type == rct::RCTTypeSimple) { - for ( i = 0; i < inputs_size; i++) { - offset = set_command_header(INS_VALIDATE, 0x01, i+2); - //options - this->buffer_send[offset] = (i==inputs_size-1)? 0x00:0x80; - offset += 1; - //pseudoOut - memmove(this->buffer_send+offset, data+data_offset,32); - offset += 32; - data_offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - } - } - - // ====== Aout, Bout, AKout, C, v, k ====== - kv_offset = data_offset; - if (type==rct::RCTTypeBulletproof2) { - C_offset = kv_offset+ (8)*outputs_size; - } else { - C_offset = kv_offset+ (32+32)*outputs_size; - } - for ( i = 0; i < outputs_size; i++) { - ABPkeys outKeys; - bool found; - - found = this->key_map.find(outPk[i].dest, outKeys); - if (!found) { - log_hexbuffer("Pout not found", (char*)outPk[i].dest.bytes, 32); - CHECK_AND_ASSERT_THROW_MES(found, "Pout not found"); - } - offset = set_command_header(INS_VALIDATE, 0x02, i+1); - //options - this->buffer_send[offset] = (i==outputs_size-1)? 0x00:0x80 ; - this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2)?0x02:0x00; - offset += 1; - if (found) { - //is_subaddress - this->buffer_send[offset] = outKeys.is_subaddress; - offset++; - //is_change_address - this->buffer_send[offset] = outKeys.is_change_address; - offset++; - //Aout - memmove(this->buffer_send+offset, outKeys.Aout.bytes, 32); - offset+=32; - //Bout - memmove(this->buffer_send+offset, outKeys.Bout.bytes, 32); - offset+=32; - //AKout - memmove(this->buffer_send+offset, outKeys.AKout.bytes, 32); - offset+=32; - } else { - // dummy: is_subaddress Aout Bout AKout - offset += 2+32*3; - } - //C - memmove(this->buffer_send+offset, data+C_offset,32); - offset += 32; - C_offset += 32; - if (type==rct::RCTTypeBulletproof2) { - //k - memset(this->buffer_send+offset, 0, 32); - offset += 32; - //v - memset(this->buffer_send+offset, 0, 32); - memmove(this->buffer_send+offset, data+kv_offset,8); - offset += 32; - kv_offset += 8; - } else { - //k - memmove(this->buffer_send+offset, data+kv_offset,32); - offset += 32; - kv_offset += 32; - //v - memmove(this->buffer_send+offset, data+kv_offset,32); - offset += 32; - kv_offset += 32; - } - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - #ifdef DEBUG_HWDEVICE - log_hexbuffer("Prehash AKV input", (char*)&this->buffer_recv[64], 3*32); - #endif - } - - // ====== C[], message, proof====== - C_offset = kv_offset; - for (i = 0; i < outputs_size; i++) { - offset = set_command_header(INS_VALIDATE, 0x03, i+1); - //options - this->buffer_send[offset] = 0x80 ; - offset += 1; - //C - memmove(this->buffer_send+offset, data+C_offset,32); - offset += 32; - C_offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - } - - offset = set_command_header_noopt(INS_VALIDATE, 0x03, i+1); - //message - memmove(this->buffer_send+offset, hashes[0].bytes,32); - offset += 32; - //proof - memmove(this->buffer_send+offset, hashes[2].bytes,32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - memmove(prehash.bytes, this->buffer_recv, 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("mlsag_prehash", "prehash", (char*)prehash_x.bytes, (char*)prehash.bytes); - #endif - - return true; - } - - - bool device_ledger::mlsag_prepare(const rct::key &H, const rct::key &xx, - rct::key &a, rct::key &aG, rct::key &aHP, rct::key &II) { - AUTO_LOCK_CMD(); - unsigned char options; - - #ifdef DEBUG_HWDEVICE - const rct::key H_x = H; - const rct::key xx_x = hw::ledger::decrypt(xx); - rct::key a_x; - rct::key aG_x; - rct::key aHP_x; - rct::key II_x; - #endif - - int offset = set_command_header_noopt(INS_MLSAG, 0x01); - //value H - memmove(this->buffer_send+offset, H.bytes, 32); - offset += 32; - //mask xin - memmove(this->buffer_send+offset, xx.bytes, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - memmove(a.bytes, &this->buffer_recv[32*0], 32); - memmove(aG.bytes, &this->buffer_recv[32*1], 32); - memmove(aHP.bytes, &this->buffer_recv[32*2], 32); - memmove(II.bytes, &this->buffer_recv[32*3], 32); - - #ifdef DEBUG_HWDEVICE - a_x = hw::ledger::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); - #endif - - return true; - } - - bool device_ledger::mlsag_prepare(rct::key &a, rct::key &aG) { - AUTO_LOCK_CMD(); - unsigned char options; - - #ifdef DEBUG_HWDEVICE - rct::key a_x; - rct::key aG_x; - #endif - - send_simple(INS_MLSAG, 0x01); - - memmove(a.bytes, &this->buffer_recv[32*0], 32); - memmove(aG.bytes, &this->buffer_recv[32*1], 32); - - #ifdef DEBUG_HWDEVICE - a_x = hw::ledger::decrypt(a); - rct::scalarmultBase(aG_x, a_x); - hw::ledger::check32("mlsag_prepare", "AG", (char*)aG_x.bytes, (char*)aG.bytes); - #endif - - return true; - } - - bool device_ledger::mlsag_hash(const rct::keyV &long_message, rct::key &c) { - AUTO_LOCK_CMD(); - unsigned char options; - size_t cnt; - - #ifdef DEBUG_HWDEVICE - const rct::keyV long_message_x = long_message; - rct::key c_x; - this->controle_device->mlsag_hash(long_message_x, c_x); - #endif - - cnt = long_message.size(); - for (size_t i = 0; ibuffer_send[offset] = - (i==(cnt-1))?0x00:0x80; //last - offset += 1; - //msg part - memmove(this->buffer_send+offset, long_message[i].bytes, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - } - - memmove(c.bytes, &this->buffer_recv[0], 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("mlsag_hash", "c", (char*)c_x.bytes, (char*)c.bytes); - #endif - - return true; - } - - bool device_ledger::mlsag_sign(const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss) { - AUTO_LOCK_CMD(); - - CHECK_AND_ASSERT_THROW_MES(dsRows<=rows, "dsRows greater than rows"); - CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "xx size does not match rows"); - CHECK_AND_ASSERT_THROW_MES(alpha.size() == rows, "alpha size does not match rows"); - CHECK_AND_ASSERT_THROW_MES(ss.size() == rows, "ss size does not match rows"); - - #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 int rows_x = rows; - const int dsRows_x = dsRows; - rct::keyV ss_x(ss.size()); - this->controle_device->mlsag_sign(c_x, xx_x, alpha_x, rows_x, dsRows_x, ss_x); - #endif - - for (size_t j = 0; j < dsRows; j++) { - int offset = set_command_header(INS_MLSAG, 0x03, j+1); - //options - this->buffer_send[offset] = 0x00; - if (j==(dsRows-1)) { - this->buffer_send[offset] |= 0x80; //last - } - offset += 1; - //xx - memmove(this->buffer_send+offset, xx[j].bytes, 32); - offset += 32; - //alpa - memmove(this->buffer_send+offset, alpha[j].bytes, 32); - offset += 32; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - - //ss - memmove(ss[j].bytes, &this->buffer_recv[0], 32); - } - - for (size_t j = dsRows; j < rows; j++) { - sc_mulsub(ss[j].bytes, c.bytes, xx[j].bytes, alpha[j].bytes); - } - - #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); - } - #endif - - return true; - } - - bool device_ledger::close_tx() { - AUTO_LOCK_CMD(); - send_simple(INS_CLOSE_TX); - return true; - } - - /* ---------------------------------------------------------- */ - - 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))); - } - - #else //WITH_DEVICE_LEDGER - - void register_all(std::map> ®istry) { - } - - #endif //WITH_DEVICE_LEDGER - - } -} - diff --git a/src/cn_utils/device/device_ledger.hpp b/src/cn_utils/device/device_ledger.hpp deleted file mode 100644 index 2f2ec7089..000000000 --- a/src/cn_utils/device/device_ledger.hpp +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2017-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include -#include -#include "device.hpp" -#include "device_io_hid.hpp" -#include -#include - -namespace hw { - - namespace ledger { - - void register_all(std::map> ®istry); - - #ifdef WITH_DEVICE_LEDGER - - namespace { - bool apdu_verbose =true; - } - - void set_apdu_verbose(bool verbose); - - class ABPkeys { - public: - rct::key Aout; - rct::key Bout; - bool is_subaddress; - bool is_change_address; - bool additional_key ; - size_t index; - rct::key Pout; - rct::key AKout; - ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, bool is_subaddress, bool is_change_address, size_t index, const rct::key& P,const rct::key& AK); - ABPkeys(const ABPkeys& keys) ; - ABPkeys() {index=0;is_subaddress=false;is_subaddress=false;is_change_address=false;} - }; - - class Keymap { - public: - std::vector ABP; - - bool find(const rct::key& P, ABPkeys& keys) const; - void add(const ABPkeys& keys); - void clear(); - void log(); - }; - - #define BUFFER_SEND_SIZE 262 - #define BUFFER_RECV_SIZE 262 - - class device_ledger : public hw::device { - private: - // Locker for concurrent access - mutable boost::recursive_mutex device_locker; - mutable boost::mutex command_locker; - - //IO - hw::io::device_io_hid hw_device; - std::string full_name; - unsigned int length_send; - unsigned char buffer_send[BUFFER_SEND_SIZE]; - unsigned int length_recv; - unsigned char buffer_recv[BUFFER_RECV_SIZE]; - unsigned int sw; - unsigned int id; - void logCMD(void); - void logRESP(void); - unsigned int exchange(unsigned int ok=0x9000, unsigned int mask=0xFFFF); - void reset_buffer(void); - int set_command_header(unsigned char ins, unsigned char p1 = 0x00, unsigned char p2 = 0x00); - int set_command_header_noopt(unsigned char ins, unsigned char p1 = 0x00, unsigned char p2 = 0x00); - void send_simple(unsigned char ins, unsigned char p1 = 0x00); - - - // hw running mode - device_mode mode; - // map public destination key to ephemeral destination key - Keymap key_map; - bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const bool is_change, - const bool need_additional, const size_t real_output_index, - const rct::key &amount_key, const crypto::public_key &out_eph_public_key); - // To speed up blockchain parsing the view key maybe handle here. - crypto::secret_key viewkey; - bool has_view_key; - - //extra debug - #ifdef DEBUG_HWDEVICE - device *controle_device; - #endif - - public: - device_ledger(); - ~device_ledger(); - - device_ledger(const device_ledger &device) = delete ; - device_ledger& operator=(const device_ledger &device) = delete; - - explicit operator bool() const override {return this->connected(); } - - bool reset(void); - - /* ======================================================================= */ - /* SETUP/TEARDOWN */ - /* ======================================================================= */ - bool set_name(const std::string &name) override; - - const std::string get_name() const override; - bool init(void) override; - bool release() override; - bool connect(void) override; - bool disconnect() override; - bool connected(void) const; - - bool set_mode(device_mode mode) override; - - device_type get_type() const override {return device_type::LEDGER;}; - - /* ======================================================================= */ - /* LOCKER */ - /* ======================================================================= */ - void lock(void) override; - void unlock(void) override; - bool try_lock(void) override; - - /* ======================================================================= */ - /* WALLET & ADDRESS */ - /* ======================================================================= */ - bool get_public_address(cryptonote::account_public_address &pubkey) override; - bool get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) override; - bool generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) override; - - - /* ======================================================================= */ - /* SUB ADDRESS */ - /* ======================================================================= */ - bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) override; - crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) override; - std::vector get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) override; - cryptonote::account_public_address get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) override; - crypto::secret_key get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) override; - - /* ======================================================================= */ - /* DERIVATION & KEY */ - /* ======================================================================= */ - bool verify_keys(const crypto::secret_key &secret_key, const crypto::public_key &public_key) override; - bool scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) override; - bool scalarmultBase(rct::key &aG, const rct::key &a) override; - bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) override; - crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) override; - bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override; - bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector &additional_derivations) override; - bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override; - bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override; - bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override; - bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) override; - bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) override; - - /* ======================================================================= */ - /* TRANSACTION */ - /* ======================================================================= */ - - bool open_tx(crypto::secret_key &tx_key) override; - - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override; - - bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_format) override; - bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_format) override; - - bool generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key, - const cryptonote::tx_destination_entry &dst_entr, const boost::optional &change_addr, const size_t output_index, - const bool &need_additional_txkeys, const std::vector &additional_tx_keys, - std::vector &additional_tx_public_keys, - std::vector &amount_keys, - crypto::public_key &out_eph_public_key) override; - - bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) override; - bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override; - bool mlsag_prepare(rct::key &a, rct::key &aG) override; - bool mlsag_hash(const rct::keyV &long_message, rct::key &c) override; - bool mlsag_sign( const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss) override; - - bool close_tx(void) override; - - }; - - - #ifdef DEBUG_HWDEVICE - extern crypto::secret_key dbg_viewkey; - extern crypto::secret_key dbg_spendkey; - #endif - - #endif //WITH_DEVICE_LEDGER - } - -} -