diff options
Diffstat (limited to '')
-rw-r--r-- | src/device/device.hpp | 1 | ||||
-rw-r--r-- | src/device/device_default.hpp | 2 | ||||
-rw-r--r-- | src/device/device_ledger.cpp | 75 | ||||
-rw-r--r-- | src/device/device_ledger.hpp | 3 | ||||
-rw-r--r-- | src/device/log.cpp | 4 | ||||
-rw-r--r-- | src/device/log.hpp | 1 | ||||
-rw-r--r-- | src/device_trezor/device_trezor.cpp | 28 | ||||
-rw-r--r-- | src/device_trezor/trezor/protocol.cpp | 225 | ||||
-rw-r--r-- | src/device_trezor/trezor/protocol.hpp | 45 |
9 files changed, 215 insertions, 169 deletions
diff --git a/src/device/device.hpp b/src/device/device.hpp index eca91006f..392703a24 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -177,6 +177,7 @@ namespace hw { 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; + virtual bool derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag) = 0; // alternative prototypes available in libringct rct::key scalarmultKey(const rct::key &P, const rct::key &a) diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp index 7d3543652..58149cdbf 100644 --- a/src/device/device_default.hpp +++ b/src/device/device_default.hpp @@ -101,7 +101,7 @@ namespace hw { 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; - bool derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag); + bool derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag) override; /* ======================================================================= */ diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index aa73e998c..8069c074e 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -266,6 +266,7 @@ namespace hw { #define INS_DERIVE_PUBLIC_KEY 0x36 #define INS_DERIVE_SECRET_KEY 0x38 #define INS_GEN_KEY_IMAGE 0x3A + #define INS_DERIVE_VIEW_TAG 0x3B #define INS_SECRET_KEY_ADD 0x3C #define INS_SECRET_KEY_SUB 0x3E #define INS_GENERATE_KEYPAIR 0x40 @@ -1308,6 +1309,54 @@ namespace hw { return true; } + bool device_ledger::derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag){ + #ifdef DEBUG_HWDEVICE + 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::view_tag view_tag_x; + log_hexbuffer("derive_view_tag: [[IN]] derivation ", derivation_x.data, 32); + log_message ("derive_view_tag: [[IN]] output_index", std::to_string(output_index_x)); + this->controle_device->derive_view_tag(derivation_x, output_index_x, view_tag_x); + log_hexbuffer("derive_view_tag: [[OUT]] view_tag ", &view_tag_x.data, 1); + #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_view_tag : PARSE mode with known viewkey"); + crypto::derive_view_tag(derivation, output_index, view_tag); + } else { + AUTO_LOCK_CMD(); + int offset = set_command_header_noopt(INS_DERIVE_VIEW_TAG); + //derivation + this->send_secret((unsigned char*)derivation.data, offset); + //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(); + + //view tag + memmove(&view_tag.data, &this->buffer_recv[0], 1); + } + + #ifdef DEBUG_HWDEVICE + hw::ledger::check1("derive_view_tag", "view_tag", &view_tag_x.data, &view_tag.data); + #endif + + return true; + } + /* ======================================================================= */ /* TRANSACTION */ /* ======================================================================= */ @@ -1548,7 +1597,6 @@ namespace hw { const size_t output_index_x = output_index; const bool need_additional_txkeys_x = need_additional_txkeys; const bool use_view_tags_x = use_view_tags; - const crypto::view_tag view_tag_x = view_tag; std::vector<crypto::secret_key> additional_tx_keys_x; for (const auto &k: additional_tx_keys) { @@ -1558,6 +1606,7 @@ namespace hw { std::vector<crypto::public_key> additional_tx_public_keys_x; std::vector<rct::key> amount_keys_x; crypto::public_key out_eph_public_key_x; + crypto::view_tag view_tag_x; log_message ("generate_output_ephemeral_keys: [[IN]] tx_version", std::to_string(tx_version_x)); //log_hexbuffer("generate_output_ephemeral_keys: [[IN]] sender_account_keys.view", sender_account_keys.m_sview_secret_key.data, 32); @@ -1575,11 +1624,15 @@ namespace hw { if(need_additional_txkeys_x) { log_hexbuffer("generate_output_ephemeral_keys: [[IN]] additional_tx_keys[oi]", additional_tx_keys_x[output_index].data, 32); } + log_message ("generate_output_ephemeral_keys: [[IN]] use_view_tags", std::to_string(use_view_tags_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, use_view_tags_x, view_tag_x); if(need_additional_txkeys_x) { log_hexbuffer("additional_tx_public_keys_x: [[OUT]] additional_tx_public_keys_x", additional_tx_public_keys_x.back().data, 32); } + if(use_view_tags_x) { + log_hexbuffer("generate_output_ephemeral_keys: [[OUT]] view_tag", &view_tag_x.data, 1); + } log_hexbuffer("generate_output_ephemeral_keys: [[OUT]] amount_keys ", (char*)amount_keys_x.back().bytes, 32); log_hexbuffer("generate_output_ephemeral_keys: [[OUT]] out_eph_public_key ", out_eph_public_key_x.data, 32); #endif @@ -1633,6 +1686,9 @@ namespace hw { memset(&this->buffer_send[offset], 0, 32); offset += 32; } + //use_view_tags + this->buffer_send[offset] = use_view_tags; + offset++; this->buffer_send[4] = offset-5; this->length_send = offset; @@ -1663,6 +1719,14 @@ namespace hw { recv_len -= 32; } + if (use_view_tags) + { + ASSERT_X(recv_len>=1, "Not enough data from device"); + memmove(&view_tag.data, &this->buffer_recv[offset], 1); + offset++; + recv_len -= 1; + } + // 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, @@ -1675,6 +1739,9 @@ namespace hw { hw::ledger::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); + if (use_view_tags) { + hw::ledger::check1("generate_output_ephemeral_keys", "view_tag", &view_tag_x.data, &view_tag.data); + } #endif return true; @@ -1860,7 +1927,7 @@ namespace hw { // ====== Aout, Bout, AKout, C, v, k ====== kv_offset = data_offset; - if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG) { + if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus) { C_offset = kv_offset+ (8)*outputs_size; } else { C_offset = kv_offset+ (32+32)*outputs_size; @@ -1877,7 +1944,7 @@ namespace hw { 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 || type==rct::RCTTypeCLSAG)?0x02:0x00; + this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus)?0x02:0x00; offset += 1; //is_subaddress this->buffer_send[offset] = outKeys.is_subaddress; @@ -1898,7 +1965,7 @@ namespace hw { memmove(this->buffer_send+offset, data+C_offset,32); offset += 32; C_offset += 32; - if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG) { + if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus) { //k memset(this->buffer_send+offset, 0, 32); offset += 32; diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index 074bfaa8d..03058c4f1 100644 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -44,7 +44,7 @@ namespace hw { /* Minimal supported version */ #define MINIMAL_APP_VERSION_MAJOR 1 - #define MINIMAL_APP_VERSION_MINOR 6 + #define MINIMAL_APP_VERSION_MINOR 8 #define MINIMAL_APP_VERSION_MICRO 0 #define VERSION(M,m,u) ((M)<<16|(m)<<8|(u)) @@ -249,6 +249,7 @@ namespace hw { 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; + bool derive_view_tag(const crypto::key_derivation &derivation, const size_t output_index, crypto::view_tag &view_tag) override; /* ======================================================================= */ /* TRANSACTION */ diff --git a/src/device/log.cpp b/src/device/log.cpp index 9b882b784..b159632d9 100644 --- a/src/device/log.cpp +++ b/src/device/log.cpp @@ -165,6 +165,10 @@ namespace hw { void check8(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted) { check(msg, info, h, d, 8, crypted); } + + void check1(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted) { + check(msg, info, h, d, 1, crypted); + } #endif } diff --git a/src/device/log.hpp b/src/device/log.hpp index 660adc63e..a0c89ec71 100644 --- a/src/device/log.hpp +++ b/src/device/log.hpp @@ -75,6 +75,7 @@ namespace hw { void check32(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted=false); void check8(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted=false); + void check1(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted=false); void set_check_verbose(bool verbose); #endif diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp index 6f7ae9a6b..58c36f2c9 100644 --- a/src/device_trezor/device_trezor.cpp +++ b/src/device_trezor/device_trezor.cpp @@ -324,8 +324,8 @@ namespace trezor { std::vector<protocol::ki::MoneroTransferDetails> mtds; std::vector<protocol::ki::MoneroExportedKeyImage> kis; - protocol::ki::key_image_data(wallet, transfers, mtds, client_version() <= 1); - protocol::ki::generate_commitment(mtds, transfers, req, client_version() <= 1); + protocol::ki::key_image_data(wallet, transfers, mtds); + protocol::ki::generate_commitment(mtds, transfers, req); EVENT_PROGRESS(0.); this->set_msg_addr<messages::monero::MoneroKeyImageExportInitRequest>(req.get()); @@ -635,11 +635,7 @@ namespace trezor { } // Step: sort - auto perm_req = signer->step_permutation(); - if (perm_req){ - auto perm_ack = this->client_exchange<messages::monero::MoneroTransactionInputsPermutationAck>(perm_req); - signer->step_permutation_ack(perm_ack); - } + signer->sort_ki(); EVENT_PROGRESS(3, 1, 1); // Step: input_vini @@ -697,13 +693,13 @@ namespace trezor { unsigned device_trezor::client_version() { auto trezor_version = get_version(); - if (trezor_version <= pack_version(2, 0, 10)){ - throw exc::TrezorException("Trezor firmware 2.0.10 and lower are not supported. Please update."); + if (trezor_version < pack_version(2, 4, 3)){ + throw exc::TrezorException("Minimal Trezor firmware version is 2.4.3. Please update."); } - unsigned client_version = 1; - if (trezor_version >= pack_version(2, 3, 1)){ - client_version = 3; + unsigned client_version = 3; + if (trezor_version >= pack_version(2, 5, 2)){ + client_version = 4; } #ifdef WITH_TREZOR_DEBUGGING @@ -739,14 +735,6 @@ namespace trezor { CHECK_AND_ASSERT_THROW_MES(init_msg, "TransactionInitRequest is empty"); CHECK_AND_ASSERT_THROW_MES(init_msg->has_tsx_data(), "TransactionInitRequest has no transaction data"); CHECK_AND_ASSERT_THROW_MES(m_features, "Device state not initialized"); // make sure the caller did not reset features - const bool nonce_required = init_msg->tsx_data().has_payment_id() && init_msg->tsx_data().payment_id().size() > 0; - - if (nonce_required && init_msg->tsx_data().payment_id().size() == 8){ - // Versions 2.0.9 and lower do not support payment ID - if (get_version() <= pack_version(2, 0, 9)) { - throw exc::TrezorException("Trezor firmware 2.0.9 and lower does not support transactions with short payment IDs or integrated addresses. Please update."); - } - } } void device_trezor::transaction_check(const protocol::tx::TData & tdata, const hw::tx_aux_data & aux_data) diff --git a/src/device_trezor/trezor/protocol.cpp b/src/device_trezor/trezor/protocol.cpp index a400e82c7..0e59a16ba 100644 --- a/src/device_trezor/trezor/protocol.cpp +++ b/src/device_trezor/trezor/protocol.cpp @@ -38,6 +38,7 @@ #include <crypto/hmac-keccak.h> #include <ringct/rctSigs.h> #include <ringct/bulletproofs.h> +#include <ringct/bulletproofs_plus.h> #include "cryptonote_config.h" #include <sodium.h> #include <sodium/crypto_verify_32.h> @@ -145,8 +146,7 @@ namespace ki { bool key_image_data(wallet_shim * wallet, const std::vector<tools::wallet2::transfer_details> & transfers, - std::vector<MoneroTransferDetails> & res, - bool need_all_additionals) + std::vector<MoneroTransferDetails> & res) { for(auto & td : transfers){ ::crypto::public_key tx_pub_key = wallet->get_tx_pub_key_from_received_outs(td); @@ -159,11 +159,7 @@ namespace ki { cres.set_internal_output_index(td.m_internal_output_index); cres.set_sub_addr_major(td.m_subaddr_index.major); cres.set_sub_addr_minor(td.m_subaddr_index.minor); - if (need_all_additionals) { - for (auto &aux : additional_tx_pub_keys) { - cres.add_additional_tx_pub_keys(key_to_string(aux)); - } - } else if (!additional_tx_pub_keys.empty() && additional_tx_pub_keys.size() > td.m_internal_output_index) { + if (!additional_tx_pub_keys.empty() && additional_tx_pub_keys.size() > td.m_internal_output_index) { cres.add_additional_tx_pub_keys(key_to_string(additional_tx_pub_keys[td.m_internal_output_index])); } } @@ -194,8 +190,7 @@ namespace ki { void generate_commitment(std::vector<MoneroTransferDetails> & mtds, const std::vector<tools::wallet2::transfer_details> & transfers, - std::shared_ptr<messages::monero::MoneroKeyImageExportInitRequest> & req, - bool need_subaddr_indices) + std::shared_ptr<messages::monero::MoneroKeyImageExportInitRequest> & req) { req = std::make_shared<messages::monero::MoneroKeyImageExportInitRequest>(); @@ -219,16 +214,6 @@ namespace ki { auto & st = search.first->second; st.insert(cur.m_subaddr_index.minor); } - - if (need_subaddr_indices) { - for (auto &x: sub_indices) { - auto subs = req->add_subs(); - subs->set_account(x.first); - for (auto minor : x.second) { - subs->add_minor_indices(minor); - } - } - } } void live_refresh_ack(const ::crypto::secret_key & view_key_priv, @@ -399,7 +384,7 @@ namespace tx { m_tx_idx = tx_idx; m_ct.tx_data = cur_src_tx(); m_multisig = false; - m_client_version = 1; + m_client_version = 3; } void Signer::extract_payment_id(){ @@ -474,25 +459,19 @@ namespace tx { auto & cur = src.outputs[i]; auto out = dst->add_outputs(); - if (i == src.real_output || need_ring_indices || client_version() <= 1) { + if (i == src.real_output || need_ring_indices) { out->set_idx(cur.first); } - if (i == src.real_output || need_ring_keys || client_version() <= 1) { + if (i == src.real_output || need_ring_keys) { translate_rct_key(out->mutable_key(), &(cur.second)); } } dst->set_real_out_tx_key(key_to_string(src.real_out_tx_key)); dst->set_real_output_in_tx_index(src.real_output_in_tx_index); - - if (client_version() <= 1) { - for (auto &cur : src.real_out_additional_tx_keys) { - dst->add_real_out_additional_tx_keys(key_to_string(cur)); - } - } else if (!src.real_out_additional_tx_keys.empty()) { + if (!src.real_out_additional_tx_keys.empty()) { dst->add_real_out_additional_tx_keys(key_to_string(src.real_out_additional_tx_keys.at(src.real_output_in_tx_index))); } - dst->set_amount(src.amount); dst->set_rct(src.rct); dst->set_mask(key_to_string(src.mask)); @@ -532,7 +511,7 @@ namespace tx { m_ct.tx.version = 2; m_ct.tx.unlock_time = tx.unlock_time; - m_client_version = (m_aux_data->client_version ? m_aux_data->client_version.get() : 1); + m_client_version = (m_aux_data->client_version ? m_aux_data->client_version.get() : 3); tsx_data.set_version(1); tsx_data.set_client_version(client_version()); @@ -543,18 +522,13 @@ namespace tx { tsx_data.set_monero_version(std::string(MONERO_VERSION) + "|" + MONERO_VERSION_TAG); tsx_data.set_hard_fork(m_aux_data->hard_fork ? m_aux_data->hard_fork.get() : 0); - if (client_version() <= 1){ - assign_to_repeatable(tsx_data.mutable_minor_indices(), tx.subaddr_indices.begin(), tx.subaddr_indices.end()); - } - // Rsig decision auto rsig_data = tsx_data.mutable_rsig_data(); m_ct.rsig_type = get_rsig_type(tx.rct_config, tx.splitted_dsts.size()); rsig_data->set_rsig_type(m_ct.rsig_type); - if (tx.rct_config.range_proof_type != rct::RangeProofBorromean){ - m_ct.bp_version = (m_aux_data->bp_version ? m_aux_data->bp_version.get() : 1); - rsig_data->set_bp_version((uint32_t) m_ct.bp_version); - } + CHECK_AND_ASSERT_THROW_MES(tx.rct_config.range_proof_type != rct::RangeProofBorromean, "Borromean rsig not supported"); + m_ct.bp_version = (m_aux_data->bp_version ? m_aux_data->bp_version.get() : 1); + rsig_data->set_bp_version((uint32_t) m_ct.bp_version); generate_rsig_batch_sizes(m_ct.grouping_vct, m_ct.rsig_type, tx.splitted_dsts.size()); assign_to_repeatable(rsig_data->mutable_grouping(), m_ct.grouping_vct.begin(), m_ct.grouping_vct.end()); @@ -652,22 +626,6 @@ namespace tx { }); } - std::shared_ptr<messages::monero::MoneroTransactionInputsPermutationRequest> Signer::step_permutation(){ - sort_ki(); - if (client_version() >= 2){ - return nullptr; - } - - auto res = std::make_shared<messages::monero::MoneroTransactionInputsPermutationRequest>(); - assign_to_repeatable(res->mutable_perm(), m_ct.source_permutation.begin(), m_ct.source_permutation.end()); - - return res; - } - - void Signer::step_permutation_ack(std::shared_ptr<const messages::monero::MoneroTransactionInputsPermutationAck> ack){ - - } - std::shared_ptr<messages::monero::MoneroTransactionInputViniRequest> Signer::step_set_vini_input(size_t idx){ CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx_data.sources.size(), "Invalid transaction index"); CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx.vin.size(), "Invalid transaction index"); @@ -711,8 +669,10 @@ namespace tx { } void Signer::step_set_output_ack(std::shared_ptr<const messages::monero::MoneroTransactionSetOutputAck> ack){ + CHECK_AND_ASSERT_THROW_MES(is_req_bulletproof(), "Borromean rsig not supported"); cryptonote::tx_out tx_out; rct::Bulletproof bproof{}; + rct::BulletproofPlus bproof_plus{}; rct::ctkey out_pk{}; rct::ecdhTuple ecdh{}; @@ -727,7 +687,7 @@ namespace tx { rsig_buff = rsig_data.rsig(); } - if (client_version() >= 1 && rsig_data.has_mask()){ + if (rsig_data.has_mask()){ rct::key cmask{}; string_to_key(cmask, rsig_data.mask()); m_ct.rsig_gamma.emplace_back(cmask); @@ -751,22 +711,32 @@ namespace tx { memcpy(ecdh.amount.bytes, ack->ecdh_info().data(), 8); } - if (has_rsig && is_req_bulletproof() && !cn_deserialize(rsig_buff, bproof)){ - throw exc::ProtocolException("Cannot deserialize bulletproof rangesig"); - } - m_ct.tx.vout.emplace_back(tx_out); m_ct.tx_out_hmacs.push_back(ack->vouti_hmac()); m_ct.tx_out_pk.emplace_back(out_pk); m_ct.tx_out_ecdh.emplace_back(ecdh); - // ClientV0, if no rsig was generated on Trezor, do not continue. - // ClientV1+ generates BP after all masks in the current batch are generated - if (!has_rsig || (client_version() >= 1 && is_offloading())){ + rsig_v bp_obj{}; + if (has_rsig) { + bool deserialize_success; + if (is_req_bulletproof_plus()) { + deserialize_success = cn_deserialize(rsig_buff, bproof_plus); + bp_obj = bproof_plus; + } else { + deserialize_success = cn_deserialize(rsig_buff, bproof); + bp_obj = bproof; + } + if (!deserialize_success) { + throw exc::ProtocolException("Cannot deserialize bulletproof rangesig"); + } + } + + // Generates BP after all masks in the current batch are generated + if (!has_rsig || is_offloading()){ return; } - process_bproof(bproof); + process_bproof(bp_obj); m_ct.cur_batch_idx += 1; m_ct.cur_output_in_batch_idx = 0; } @@ -791,13 +761,21 @@ namespace tx { masks.push_back(m_ct.rsig_gamma[bidx]); } - auto bp = bulletproof_PROVE(amounts, masks); - auto serRsig = cn_serialize(bp); - m_ct.tx_out_rsigs.emplace_back(bp); + std::string serRsig; + if (is_req_bulletproof_plus()) { + auto bp = bulletproof_plus_PROVE(amounts, masks); + serRsig = cn_serialize(bp); + m_ct.tx_out_rsigs.emplace_back(bp); + } else { + auto bp = bulletproof_PROVE(amounts, masks); + serRsig = cn_serialize(bp); + m_ct.tx_out_rsigs.emplace_back(bp); + } + rsig_data.set_rsig(serRsig); } - void Signer::process_bproof(rct::Bulletproof & bproof){ + void Signer::process_bproof(rsig_v & bproof){ CHECK_AND_ASSERT_THROW_MES(m_ct.cur_batch_idx < m_ct.grouping_vct.size(), "Invalid batch index"); auto batch_size = m_ct.grouping_vct[m_ct.cur_batch_idx]; for (size_t i = 0; i < batch_size; ++i){ @@ -806,12 +784,22 @@ namespace tx { rct::key commitment = m_ct.tx_out_pk[bidx].mask; commitment = rct::scalarmultKey(commitment, rct::INV_EIGHT); - bproof.V.push_back(commitment); + if (is_req_bulletproof_plus()) { + boost::get<rct::BulletproofPlus>(bproof).V.push_back(commitment); + } else { + boost::get<rct::Bulletproof>(bproof).V.push_back(commitment); + } } m_ct.tx_out_rsigs.emplace_back(bproof); - if (!rct::bulletproof_VERIFY(boost::get<rct::Bulletproof>(m_ct.tx_out_rsigs.back()))) { - throw exc::ProtocolException("Returned range signature is invalid"); + if (is_req_bulletproof_plus()) { + if (!rct::bulletproof_plus_VERIFY(boost::get<rct::BulletproofPlus>(m_ct.tx_out_rsigs.back()))) { + throw exc::ProtocolException("Returned range signature is invalid"); + } + } else { + if (!rct::bulletproof_VERIFY(boost::get<rct::Bulletproof>(m_ct.tx_out_rsigs.back()))) { + throw exc::ProtocolException("Returned range signature is invalid"); + } } } @@ -840,6 +828,7 @@ namespace tx { } void Signer::step_all_outs_set_ack(std::shared_ptr<const messages::monero::MoneroTransactionAllOutSetAck> ack, hw::device &hwdev){ + CHECK_AND_ASSERT_THROW_MES(is_req_bulletproof(), "Borromean rsig not supported"); m_ct.rv = std::make_shared<rct::rctSig>(); m_ct.rv->txnFee = ack->rv().txn_fee(); m_ct.rv->type = static_cast<uint8_t>(ack->rv().rv_type()); @@ -864,24 +853,15 @@ namespace tx { // RctSig auto num_sources = m_ct.tx_data.sources.size(); - if (is_simple() || is_req_bulletproof()){ - auto dst = &m_ct.rv->pseudoOuts; - if (is_bulletproof()){ - dst = &m_ct.rv->p.pseudoOuts; - } - - dst->clear(); - for (const auto &pseudo_out : m_ct.pseudo_outs) { - dst->emplace_back(); - string_to_key(dst->back(), pseudo_out); - } - - m_ct.rv->mixRing.resize(num_sources); - } else { - m_ct.rv->mixRing.resize(m_ct.tsx_data.mixin()); - m_ct.rv->mixRing[0].resize(num_sources); + auto dst = &m_ct.rv->p.pseudoOuts; + dst->clear(); + for (const auto &pseudo_out : m_ct.pseudo_outs) { + dst->emplace_back(); + string_to_key(dst->back(), pseudo_out); } + m_ct.rv->mixRing.resize(num_sources); + CHECK_AND_ASSERT_THROW_MES(m_ct.tx_out_pk.size() == m_ct.tx_out_ecdh.size(), "Invalid vector sizes"); for(size_t i = 0; i < m_ct.tx_out_ecdh.size(); ++i){ m_ct.rv->outPk.push_back(m_ct.tx_out_pk[i]); @@ -889,10 +869,10 @@ namespace tx { } for(size_t i = 0; i < m_ct.tx_out_rsigs.size(); ++i){ - if (is_bulletproof()){ - m_ct.rv->p.bulletproofs.push_back(boost::get<rct::Bulletproof>(m_ct.tx_out_rsigs[i])); + if (is_req_bulletproof_plus()) { + m_ct.rv->p.bulletproofs_plus.push_back(boost::get<rct::BulletproofPlus>(m_ct.tx_out_rsigs[i])); } else { - m_ct.rv->p.rangeSigs.push_back(boost::get<rct::rangeSig>(m_ct.tx_out_rsigs[i])); + m_ct.rv->p.bulletproofs.push_back(boost::get<rct::Bulletproof>(m_ct.tx_out_rsigs[i])); } } @@ -936,8 +916,8 @@ namespace tx { void Signer::step_sign_input_ack(std::shared_ptr<const messages::monero::MoneroTransactionSignInputAck> ack){ m_ct.signatures.push_back(ack->signature()); - // Sync updated pseudo_outputs, client_version>=1, HF10+ - if (client_version() >= 1 && ack->has_pseudo_out()){ + // Sync updated pseudo_outputs + if (ack->has_pseudo_out()){ CHECK_AND_ASSERT_THROW_MES(m_ct.cur_input_idx < m_ct.pseudo_outs.size(), "Invalid pseudo-out index"); m_ct.pseudo_outs[m_ct.cur_input_idx] = ack->pseudo_out(); if (is_bulletproof()){ @@ -955,6 +935,8 @@ namespace tx { } void Signer::step_final_ack(std::shared_ptr<const messages::monero::MoneroTransactionFinalAck> ack){ + CHECK_AND_ASSERT_THROW_MES(is_clsag(), "Only CLSAGs signatures are supported"); + if (m_multisig){ auto & cout_key = ack->cout_key(); for(auto & cur : m_ct.couts){ @@ -975,47 +957,34 @@ namespace tx { m_ct.enc_keys = ack->tx_enc_keys(); // Opening the sealed signatures - if (client_version() >= 3){ - if(!ack->has_opening_key()){ - throw exc::ProtocolException("Client version 3+ requires sealed signatures"); - } + if(!ack->has_opening_key()){ + throw exc::ProtocolException("Client version 3+ requires sealed signatures"); + } - for(size_t i = 0; i < m_ct.signatures.size(); ++i){ - CHECK_AND_ASSERT_THROW_MES(m_ct.signatures[i].size() > crypto::chacha::TAG_SIZE, "Invalid signature size"); - std::string nonce = compute_sealing_key(ack->opening_key(), i, true); - std::string key = compute_sealing_key(ack->opening_key(), i, false); - size_t plen = m_ct.signatures[i].size() - crypto::chacha::TAG_SIZE; - std::unique_ptr<uint8_t[]> plaintext(new uint8_t[plen]); - uint8_t * buff = plaintext.get(); - - protocol::crypto::chacha::decrypt( - m_ct.signatures[i].data(), - m_ct.signatures[i].size(), - reinterpret_cast<const uint8_t *>(key.data()), - reinterpret_cast<const uint8_t *>(nonce.data()), - reinterpret_cast<char *>(buff), &plen); - m_ct.signatures[i].assign(reinterpret_cast<const char *>(buff), plen); - } + for(size_t i = 0; i < m_ct.signatures.size(); ++i){ + CHECK_AND_ASSERT_THROW_MES(m_ct.signatures[i].size() > crypto::chacha::TAG_SIZE, "Invalid signature size"); + std::string nonce = compute_sealing_key(ack->opening_key(), i, true); + std::string key = compute_sealing_key(ack->opening_key(), i, false); + size_t plen = m_ct.signatures[i].size() - crypto::chacha::TAG_SIZE; + std::unique_ptr<uint8_t[]> plaintext(new uint8_t[plen]); + uint8_t * buff = plaintext.get(); + + protocol::crypto::chacha::decrypt( + m_ct.signatures[i].data(), + m_ct.signatures[i].size(), + reinterpret_cast<const uint8_t *>(key.data()), + reinterpret_cast<const uint8_t *>(nonce.data()), + reinterpret_cast<char *>(buff), &plen); + m_ct.signatures[i].assign(reinterpret_cast<const char *>(buff), plen); } - if (m_ct.rv->type == rct::RCTTypeCLSAG){ - m_ct.rv->p.CLSAGs.reserve(m_ct.signatures.size()); - for (size_t i = 0; i < m_ct.signatures.size(); ++i) { - rct::clsag clsag; - if (!cn_deserialize(m_ct.signatures[i], clsag)) { - throw exc::ProtocolException("Cannot deserialize clsag[i]"); - } - m_ct.rv->p.CLSAGs.push_back(clsag); - } - } else { - m_ct.rv->p.MGs.reserve(m_ct.signatures.size()); - for (size_t i = 0; i < m_ct.signatures.size(); ++i) { - rct::mgSig mg; - if (!cn_deserialize(m_ct.signatures[i], mg)) { - throw exc::ProtocolException("Cannot deserialize mg[i]"); - } - m_ct.rv->p.MGs.push_back(mg); + m_ct.rv->p.CLSAGs.reserve(m_ct.signatures.size()); + for (size_t i = 0; i < m_ct.signatures.size(); ++i) { + rct::clsag clsag; + if (!cn_deserialize(m_ct.signatures[i], clsag)) { + throw exc::ProtocolException("Cannot deserialize clsag[i]"); } + m_ct.rv->p.CLSAGs.push_back(clsag); } m_ct.tx.rct_signatures = *(m_ct.rv); diff --git a/src/device_trezor/trezor/protocol.hpp b/src/device_trezor/trezor/protocol.hpp index 858db1520..fa8355200 100644 --- a/src/device_trezor/trezor/protocol.hpp +++ b/src/device_trezor/trezor/protocol.hpp @@ -116,8 +116,7 @@ namespace ki { */ bool key_image_data(wallet_shim * wallet, const std::vector<tools::wallet2::transfer_details> & transfers, - std::vector<MoneroTransferDetails> & res, - bool need_all_additionals=false); + std::vector<MoneroTransferDetails> & res); /** * Computes a hash over MoneroTransferDetails. Commitment used in the KI sync. @@ -129,8 +128,7 @@ namespace ki { */ void generate_commitment(std::vector<MoneroTransferDetails> & mtds, const std::vector<tools::wallet2::transfer_details> & transfers, - std::shared_ptr<messages::monero::MoneroKeyImageExportInitRequest> & req, - bool need_subaddr_indices=false); + std::shared_ptr<messages::monero::MoneroKeyImageExportInitRequest> & req); /** * Processes Live refresh step response, parses KI, checks the signature @@ -166,7 +164,7 @@ namespace tx { ::crypto::secret_key compute_enc_key(const ::crypto::secret_key & private_view_key, const std::string & aux, const std::string & salt); std::string compute_sealing_key(const std::string & master_key, size_t idx, bool is_iv=false); - typedef boost::variant<rct::rangeSig, rct::Bulletproof> rsig_v; + typedef boost::variant<rct::Bulletproof, rct::BulletproofPlus> rsig_v; /** * Transaction signer state holder. @@ -247,7 +245,7 @@ namespace tx { void compute_integrated_indices(TsxData * tsx_data); bool should_compute_bp_now() const; void compute_bproof(messages::monero::MoneroTransactionRsigData & rsig_data); - void process_bproof(rct::Bulletproof & bproof); + void process_bproof(rsig_v & bproof); void set_tx_input(MoneroTransactionSourceEntry * dst, size_t idx, bool need_ring_keys=false, bool need_ring_indices=false); public: @@ -260,8 +258,6 @@ namespace tx { void step_set_input_ack(std::shared_ptr<const messages::monero::MoneroTransactionSetInputAck> ack); void sort_ki(); - std::shared_ptr<messages::monero::MoneroTransactionInputsPermutationRequest> step_permutation(); - void step_permutation_ack(std::shared_ptr<const messages::monero::MoneroTransactionInputsPermutationAck> ack); std::shared_ptr<messages::monero::MoneroTransactionInputViniRequest> step_set_vini_input(size_t idx); void step_set_vini_input_ack(std::shared_ptr<const messages::monero::MoneroTransactionInputViniAck> ack); @@ -290,11 +286,15 @@ namespace tx { return m_client_version; } - bool is_simple() const { + uint8_t get_rv_type() const { if (!m_ct.rv){ throw std::invalid_argument("RV not initialized"); } - auto tp = m_ct.rv->type; + return m_ct.rv->type; + } + + bool is_simple() const { + auto tp = get_rv_type(); return tp == rct::RCTTypeSimple; } @@ -302,12 +302,27 @@ namespace tx { return m_ct.tx_data.rct_config.range_proof_type != rct::RangeProofBorromean; } + bool is_req_clsag() const { + return is_req_bulletproof() && m_ct.tx_data.rct_config.bp_version >= 3; + } + + bool is_req_bulletproof_plus() const { + return is_req_bulletproof() && m_ct.tx_data.rct_config.bp_version == 4; // rct::genRctSimple + } + bool is_bulletproof() const { - if (!m_ct.rv){ - throw std::invalid_argument("RV not initialized"); - } - auto tp = m_ct.rv->type; - return tp == rct::RCTTypeBulletproof || tp == rct::RCTTypeBulletproof2 || tp == rct::RCTTypeCLSAG; + auto tp = get_rv_type(); + return rct::is_rct_bulletproof(tp) || rct::is_rct_bulletproof_plus(tp); + } + + bool is_bulletproof_plus() const { + auto tp = get_rv_type(); + return rct::is_rct_bulletproof_plus(tp); + } + + bool is_clsag() const { + auto tp = get_rv_type(); + return rct::is_rct_clsag(tp); } bool is_offloading() const { |