aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiccardo Spagni <ric@spagni.net>2019-04-01 17:35:11 +0200
committerRiccardo Spagni <ric@spagni.net>2019-04-01 17:35:12 +0200
commitb8ab510f238e5a4b9907ea09ed0f364b34ab1ae5 (patch)
tree25661fc3125132dff3f48a4f1aa19676f8e74c0e
parentMerge pull request #5349 (diff)
parentAdd get_tx_proof support, needed for new sanity check (diff)
downloadmonero-b8ab510f238e5a4b9907ea09ed0f364b34ab1ae5.tar.xz
Merge pull request #5332
7c440915 Add get_tx_proof support, needed for new sanity check (cslashm) 98fdcb2a Add support for V11 protocol with BulletProofV2 and short amount. New scheme key destination contrfol Fix dummy decryption in debug mode (cslashm) 3a981a33 Add application version compatibility check. (cslashm)
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.h7
-rw-r--r--src/device/CMakeLists.txt2
-rw-r--r--src/device/device.hpp21
-rw-r--r--src/device/device_default.cpp10
-rw-r--r--src/device/device_default.hpp6
-rw-r--r--src/device/device_ledger.cpp264
-rw-r--r--src/device/device_ledger.hpp20
-rw-r--r--src/device/log.hpp13
-rw-r--r--src/ringct/rctSigs.cpp8
-rw-r--r--src/simplewallet/simplewallet.cpp5
-rw-r--r--src/wallet/wallet2.cpp50
11 files changed, 306 insertions, 100 deletions
diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h
index cb1561c2d..d38aa7474 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.h
+++ b/src/cryptonote_core/cryptonote_tx_utils.h
@@ -104,6 +104,13 @@ namespace cryptonote
std::vector<rct::key> &amount_keys,
crypto::public_key &out_eph_public_key) ;
+ 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<cryptonote::account_public_address> &change_addr, const size_t output_index,
+ const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys,
+ std::vector<crypto::public_key> &additional_tx_public_keys,
+ std::vector<rct::key> &amount_keys,
+ crypto::public_key &out_eph_public_key) ;
+
bool generate_genesis_block(
block& bl
, std::string const & genesis_tx
diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt
index ffa1458b0..0b0686f61 100644
--- a/src/device/CMakeLists.txt
+++ b/src/device/CMakeLists.txt
@@ -75,4 +75,6 @@ target_link_libraries(device
${OPENSSL_CRYPTO_LIBRARIES}
${Boost_SERIALIZATION_LIBRARY}
PRIVATE
+ version
+ ${Blocks}
${EXTRA_LIBRARIES})
diff --git a/src/device/device.hpp b/src/device/device.hpp
index 65b38361b..2e485b1d6 100644
--- a/src/device/device.hpp
+++ b/src/device/device.hpp
@@ -27,21 +27,6 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
-
-/* Note about debug:
- * To debug Device you can def the following :
- * #define DEBUG_HWDEVICE
- * Activate debug mechanism:
- * - Add more trace
- * - All computation done by device are checked by default device.
- * Required IODUMMYCRYPT_HWDEVICE or IONOCRYPT_HWDEVICE for fully working
- * #define IODUMMYCRYPT_HWDEVICE 1
- * - It assumes sensitive data encryption is is off on device side. a XOR with 0x55. This allow Ledger Class to make check on clear value
- * #define IONOCRYPT_HWDEVICE 1
- * - It assumes sensitive data encryption is off on device side.
- */
-
-
#pragma once
#include "crypto/crypto.h"
@@ -211,6 +196,10 @@ namespace hw {
/* TRANSACTION */
/* ======================================================================= */
+ virtual void generate_tx_proof(const crypto::hash &prefix_hash,
+ const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
+ crypto::signature &sig) = 0;
+
virtual bool open_tx(crypto::secret_key &tx_key) = 0;
virtual bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) = 0;
@@ -220,6 +209,8 @@ namespace hw {
return encrypt_payment_id(payment_id, public_key, secret_key);
}
+ virtual rct::key genCommitmentMask(const rct::key &amount_key) = 0;
+
virtual bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_amount) = 0;
virtual bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_amount) = 0;
diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp
index 999fbc22f..dc06ce237 100644
--- a/src/device/device_default.cpp
+++ b/src/device/device_default.cpp
@@ -37,7 +37,6 @@
#include "cryptonote_core/cryptonote_tx_utils.h"
#include "ringct/rctOps.h"
-#include "log.hpp"
#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
#define CHACHA8_KEY_TAIL 0x8c
@@ -273,6 +272,11 @@ namespace hw {
/* ======================================================================= */
/* TRANSACTION */
/* ======================================================================= */
+ void device_default::generate_tx_proof(const crypto::hash &prefix_hash,
+ const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
+ crypto::signature &sig) {
+ crypto::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
+ }
bool device_default::open_tx(crypto::secret_key &tx_key) {
cryptonote::keypair txkey = cryptonote::keypair::generate(*this);
@@ -349,6 +353,10 @@ namespace hw {
return true;
}
+ rct::key device_default::genCommitmentMask(const rct::key &amount_key) {
+ return rct::genCommitmentMask(amount_key);
+ }
+
bool device_default::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_amount) {
rct::ecdhEncode(unmasked, sharedSec, short_amount);
return true;
diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp
index 90d39495b..5252d4129 100644
--- a/src/device/device_default.hpp
+++ b/src/device/device_default.hpp
@@ -107,10 +107,16 @@ namespace hw {
/* TRANSACTION */
/* ======================================================================= */
+ void generate_tx_proof(const crypto::hash &prefix_hash,
+ const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
+ crypto::signature &sig) override;
+
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;
+ rct::key genCommitmentMask(const rct::key &amount_key) override;
+
bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_amount) override;
bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_amount) override;
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index 0f197272c..d6033e189 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -27,8 +27,8 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
+#include "version.h"
#include "device_ledger.hpp"
-#include "log.hpp"
#include "ringct/rctOps.h"
#include "cryptonote_basic/account.h"
#include "cryptonote_basic/subaddress_index.h"
@@ -173,6 +173,7 @@ namespace hw {
#define INS_SET_SIGNATURE_MODE 0x72
#define INS_GET_ADDITIONAL_KEY 0x74
#define INS_STEALTH 0x76
+ #define INS_GEN_COMMITMENT_MASK 0x77
#define INS_BLIND 0x78
#define INS_UNBLIND 0x7A
#define INS_GEN_TXOUT_KEYS 0x7B
@@ -180,6 +181,7 @@ namespace hw {
#define INS_MLSAG 0x7E
#define INS_CLOSE_TX 0x80
+ #define INS_GET_TX_PROOF 0xA0
#define INS_GET_RESPONSE 0xc0
@@ -302,8 +304,24 @@ namespace hw {
}
bool device_ledger::reset() {
- send_simple(INS_RESET);
- return true;
+ reset_buffer();
+ int offset = set_command_header_noopt(INS_RESET);
+ memmove(this->buffer_send+offset, MONERO_VERSION, strlen(MONERO_VERSION));
+ offset += strlen(MONERO_VERSION);
+ this->buffer_send[4] = offset-5;
+ this->length_send = offset;
+ this->exchange();
+
+ ASSERT_X(this->length_recv>=3, "Communication error, less than three bytes received. Check your application version.");
+
+ unsigned int device_version = 0;
+ device_version = VERSION(this->buffer_recv[0], this->buffer_recv[1], this->buffer_recv[2]);
+
+ ASSERT_X (device_version >= MINIMAL_APP_VERSION,
+ "Unsupported device application version: " << VERSION_MAJOR(device_version)<<"."<<VERSION_MINOR(device_version)<<"."<<VERSION_MICRO(device_version) <<
+ " At least " << MINIMAL_APP_VERSION_MAJOR<<"."<<MINIMAL_APP_VERSION_MINOR<<"."<<MINIMAL_APP_VERSION_MICRO<<" is required.");
+
+ return true;
}
unsigned int device_ledger::exchange(unsigned int ok, unsigned int mask) {
@@ -314,9 +332,9 @@ namespace hw {
this->length_recv -= 2;
this->sw = (this->buffer_recv[length_recv]<<8) | this->buffer_recv[length_recv+1];
+ logRESP();
ASSERT_SW(this->sw,ok,msk);
- logRESP();
return this->sw;
}
@@ -790,7 +808,11 @@ namespace hw {
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;
+ rct::key aG_x;
+ log_hexbuffer("sc_secret_add: [[IN]] a ", (char*)a_x.data, 32);
+ log_hexbuffer("sc_secret_add: [[IN]] b ", (char*)b_x.data, 32);
this->controle_device->sc_secret_add(r_x, a_x, b_x);
+ log_hexbuffer("sc_secret_add: [[OUT]] aG", (char*)r_x.data, 32);
#endif
int offset = set_command_header_noopt(INS_SECRET_KEY_ADD);
@@ -825,6 +847,11 @@ namespace hw {
#ifdef DEBUG_HWDEVICE
crypto::public_key pub_x;
crypto::secret_key sec_x;
+ crypto::secret_key recovery_key_x;
+ if (recover) {
+ recovery_key_x = hw::ledger::decrypt(recovery_key);
+ log_hexbuffer("generate_keys: [[IN]] pub", (char*)recovery_key_x.data, 32);
+ }
#endif
send_simple(INS_GENERATE_KEYPAIR);
@@ -836,6 +863,9 @@ namespace hw {
#ifdef DEBUG_HWDEVICE
crypto::secret_key sec_clear = hw::ledger::decrypt(sec);
sec_x = sec_clear;
+ log_hexbuffer("generate_keys: [[OUT]] pub", (char*)pub.data, 32);
+ log_hexbuffer("generate_keys: [[OUT]] sec", (char*)sec_clear.data, 32);
+
crypto::secret_key_to_public_key(sec_x,pub_x);
hw::ledger::check32("generate_keys", "pub", pub_x.data, pub.data);
#endif
@@ -850,7 +880,7 @@ namespace hw {
#ifdef DEBUG_HWDEVICE
const crypto::public_key pub_x = pub;
- const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
+ const crypto::secret_key sec_x = (sec == rct::rct2sk(rct::I)) ? sec: 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);
@@ -866,7 +896,6 @@ namespace hw {
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);
@@ -885,11 +914,11 @@ namespace hw {
}
#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);
- }
+ 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
@@ -1050,7 +1079,7 @@ namespace hw {
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");
+ log_message("FAIL secret_key_to_public_key", "secret_key rejected");
}
#endif
@@ -1112,6 +1141,75 @@ namespace hw {
/* TRANSACTION */
/* ======================================================================= */
+ void device_ledger::generate_tx_proof(const crypto::hash &prefix_hash,
+ const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
+ crypto::signature &sig) {
+
+ AUTO_LOCK_CMD();
+
+ #ifdef DEBUG_HWDEVICE
+ const crypto::hash prefix_hash_x = prefix_hash;
+ const crypto::public_key R_x = R;
+ const crypto::public_key A_x = A;
+ const boost::optional<crypto::public_key> B_x = B;
+ const crypto::public_key D_x = D;
+ const crypto::secret_key r_x = hw::ledger::decrypt(r);
+ crypto::signature sig_x;
+ log_hexbuffer("generate_tx_proof: [[IN]] prefix_hash ", prefix_hash_x.data, 32);
+ log_hexbuffer("generate_tx_proof: [[IN]] R ", R_x.data, 32);
+ log_hexbuffer("generate_tx_proof: [[IN]] A ", A_x.data, 32);
+ if (B_x) {
+ log_hexbuffer("generate_tx_proof: [[IN]] B ", (*B_x).data, 32);
+ }
+ log_hexbuffer("generate_tx_proof: [[IN]] D ", D_x.data, 32);
+ log_hexbuffer("generate_tx_proof: [[IN]] r ", r_x.data, 32);
+ #endif
+
+
+ int offset = set_command_header(INS_GET_TX_PROOF);
+ //options
+ this->buffer_send[offset] = B?0x01:0x00;
+ offset += 1;
+ //prefix_hash
+ memmove(&this->buffer_send[offset], prefix_hash.data, 32);
+ offset += 32;
+ // R
+ memmove(&this->buffer_send[offset], R.data, 32);
+ offset += 32;
+ // A
+ memmove(&this->buffer_send[offset], A.data, 32);
+ offset += 32;
+ // B
+ if (B) {
+ memmove(&this->buffer_send[offset], (*B).data, 32);
+ } else {
+ memset(&this->buffer_send[offset], 0, 32);
+ }
+ offset += 32;
+ // D
+ memmove(&this->buffer_send[offset], D.data, 32);
+ offset += 32;
+ // r
+ memmove(&this->buffer_send[offset], r.data, 32);
+ offset += 32;
+
+ this->buffer_send[4] = offset-5;
+ this->length_send = offset;
+ this->exchange();
+
+ memmove(sig.c.data, &this->buffer_recv[0], 32);
+ memmove(sig.r.data, &this->buffer_recv[32], 32);
+ #ifdef DEBUG_HWDEVICE
+ log_hexbuffer("GENERATE_TX_PROOF: **c** ", sig.c.data, sizeof( sig.c.data));
+ log_hexbuffer("GENERATE_TX_PROOF: **r** ", sig.r.data, sizeof( sig.r.data));
+
+ this->controle_device->generate_tx_proof(prefix_hash_x, R_x, A_x, B_x, D_x, r_x, sig_x);
+ hw::ledger::check32("generate_tx_proof", "c", sig_x.c.data, sig.c.data);
+ hw::ledger::check32("generate_tx_proof", "r", sig_x.r.data, sig.r.data);
+
+ #endif
+ }
+
bool device_ledger::open_tx(crypto::secret_key &tx_key) {
AUTO_LOCK_CMD();
@@ -1130,7 +1228,11 @@ namespace hw {
this->exchange();
memmove(tx_key.data, &this->buffer_recv[32], 32);
-
+ #ifdef DEBUG_HWDEVICE
+ const crypto::secret_key r_x = hw::ledger::decrypt(tx_key);
+ log_hexbuffer("open_tx: [[OUT]] R ", (char*)&this->buffer_recv[0], 32);
+ log_hexbuffer("open_tx: [[OUT]] r ", r_x.data, 32);
+ #endif
return true;
}
@@ -1141,7 +1243,11 @@ namespace hw {
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;
+ log_hexbuffer("encrypt_payment_id: [[IN]] payment_id ", payment_id_x.data, 32);
+ log_hexbuffer("encrypt_payment_id: [[IN]] public_key ", public_key_x.data, 32);
+ log_hexbuffer("encrypt_payment_id: [[IN]] secret_key ", secret_key_x.data, 32);
this->controle_device->encrypt_payment_id(payment_id_x, public_key_x, secret_key_x);
+ log_hexbuffer("encrypt_payment_id: [[OUT]] payment_id ", payment_id_x.data, 32);
#endif
int offset = set_command_header_noopt(INS_STEALTH);
@@ -1178,49 +1284,58 @@ namespace hw {
#ifdef DEBUG_HWDEVICE
const size_t &tx_version_x = tx_version;
- const cryptonote::account_keys sender_account_keys_x = sender_account_keys;
+ const cryptonote::account_keys sender_account_keys_x = hw::ledger::decrypt(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<cryptonote::account_public_address> &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<crypto::secret_key> &additional_tx_keys_x = additional_tx_keys;
+ const crypto::public_key txkey_pub_x = txkey_pub;
+ const crypto::secret_key tx_key_x = hw::ledger::decrypt(tx_key);
+ const cryptonote::tx_destination_entry dst_entr_x = dst_entr;
+ const boost::optional<cryptonote::account_public_address> change_addr_x = change_addr;
+ const size_t output_index_x = output_index;
+ const bool need_additional_txkeys_x = need_additional_txkeys;
+
+ std::vector<crypto::secret_key> additional_tx_keys_x;
+ for (const auto k: additional_tx_keys) {
+ additional_tx_keys_x.push_back(hw::ledger::decrypt(k));
+ }
+
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;
+
+ 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);
+ //log_hexbuffer("generate_output_ephemeral_keys: [[IN]] sender_account_keys.spend", sender_account_keys.m_spend_secret_key.data, 32);
+ log_hexbuffer("generate_output_ephemeral_keys: [[IN]] txkey_pub", txkey_pub_x.data, 32);
+ log_hexbuffer("generate_output_ephemeral_keys: [[IN]] tx_key", tx_key_x.data, 32);
+ log_hexbuffer("generate_output_ephemeral_keys: [[IN]] dst_entr.view", dst_entr_x.addr.m_view_public_key.data, 32);
+ log_hexbuffer("generate_output_ephemeral_keys: [[IN]] dst_entr.spend", dst_entr_x.addr.m_spend_public_key.data, 32);
+ if (change_addr) {
+ log_hexbuffer("generate_output_ephemeral_keys: [[IN]] change_addr.view", (*change_addr_x).m_view_public_key.data, 32);
+ log_hexbuffer("generate_output_ephemeral_keys: [[IN]] change_addr.spend", (*change_addr_x).m_spend_public_key.data, 32);
+ }
+ log_message ("generate_output_ephemeral_keys: [[IN]] output_index", std::to_string(output_index_x));
+ log_message ("generate_output_ephemeral_keys: [[IN]] need_additional_txkeys", std::to_string(need_additional_txkeys_x));
+ if(need_additional_txkeys_x) {
+ log_hexbuffer("generate_output_ephemeral_keys: [[IN]] additional_tx_keys[oi]", additional_tx_keys_x[output_index].data, 32);
+ }
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);
+ 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);
+ }
+ 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
+ ASSERT_X(tx_version > 1, "TX version not supported"<<tx_version);
+
// 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;
@@ -1228,8 +1343,11 @@ namespace hw {
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);
+ //tx_key
+ memmove(&this->buffer_send[offset], tx_key.data, 32);
+ offset += 32;
+ //txkey_pub
+ memmove(&this->buffer_send[offset], txkey_pub.data, 32);
offset += 32;
//Aout
memmove(&this->buffer_send[offset], dst_entr.addr.m_view_public_key.data, 32);
@@ -1244,6 +1362,7 @@ namespace hw {
this->buffer_send[offset+3] = output_index>>0;
offset += 4;
//is_change,
+ bool is_change = (change_addr && dst_entr.addr == *change_addr);
this->buffer_send[offset] = is_change;
offset++;
//is_subaddress
@@ -1252,6 +1371,13 @@ namespace hw {
//need_additional_key
this->buffer_send[offset] = need_additional_txkeys;
offset++;
+ //additional_tx_key
+ if (need_additional_txkeys) {
+ memmove(&this->buffer_send[offset], additional_txkey.sec.data, 32);
+ } else {
+ memset(&this->buffer_send[offset], 0, 32);
+ }
+ offset += 32;
this->buffer_send[4] = offset-5;
this->length_send = offset;
@@ -1259,15 +1385,8 @@ namespace hw {
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)
+
+ //if (tx_version > 1)
{
ASSERT_X(recv_len>=32, "Not enought data from device");
crypto::secret_key scalar1;
@@ -1279,6 +1398,16 @@ namespace hw {
ASSERT_X(recv_len>=32, "Not enought data from device");
memmove(out_eph_public_key.data, &this->buffer_recv[offset], 32);
recv_len -= 32;
+ offset += 32;
+
+ 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;
+ }
// 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,
@@ -1286,9 +1415,10 @@ namespace hw {
amount_keys.back(), out_eph_public_key);
#ifdef DEBUG_HWDEVICE
+ log_hexbuffer("generate_output_ephemeral_keys: clear amount_key", (const char*)hw::ledger::decrypt(amount_keys.back()).bytes, 32);
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", "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);
#endif
@@ -1303,6 +1433,32 @@ namespace hw {
return true;
}
+ rct::key device_ledger::genCommitmentMask(const rct::key &AKout) {
+ #ifdef DEBUG_HWDEVICE
+ const rct::key AKout_x = hw::ledger::decrypt(AKout);
+ rct::key mask_x;
+ mask_x = this->controle_device->genCommitmentMask(AKout_x);
+ #endif
+
+ rct::key mask;
+ int offset = set_command_header_noopt(INS_GEN_COMMITMENT_MASK);
+ // AKout
+ memmove(this->buffer_send+offset, AKout.bytes, 32);
+ offset += 32;
+
+ this->buffer_send[4] = offset-5;
+ this->length_send = offset;
+ this->exchange();
+
+ memmove(mask.bytes, &this->buffer_recv[0], 32);
+
+ #ifdef DEBUG_HWDEVICE
+ hw::ledger::check32("genCommitmentMask", "mask", (const char*)mask_x.bytes, (const char*)mask.bytes);
+ #endif
+
+ return mask;
+ }
+
bool device_ledger::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & AKout, bool short_amount) {
AUTO_LOCK_CMD();
@@ -1334,6 +1490,7 @@ namespace hw {
memmove(unmasked.mask.bytes, &this->buffer_recv[32], 32);
#ifdef DEBUG_HWDEVICE
+ MDEBUG("ecdhEncode: Akout: "<<AKout_x);
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);
@@ -1374,6 +1531,7 @@ namespace hw {
memmove(masked.mask.bytes, &this->buffer_recv[32], 32);
#ifdef DEBUG_HWDEVICE
+ MDEBUG("ecdhEncode: Akout: "<<AKout_x);
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
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index 252354e1c..d4d98ce4a 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -33,6 +33,7 @@
#include <cstddef>
#include <string>
#include "device.hpp"
+#include "log.hpp"
#include "device_io_hid.hpp"
#include <boost/thread/mutex.hpp>
#include <boost/thread/recursive_mutex.hpp>
@@ -41,6 +42,18 @@ namespace hw {
namespace ledger {
+ /* Minimal supported version */
+ #define MINIMAL_APP_VERSION_MAJOR 1
+ #define MINIMAL_APP_VERSION_MINOR 3
+ #define MINIMAL_APP_VERSION_MICRO 1
+
+ #define VERSION(M,m,u) ((M)<<16|(m)<<8|(u))
+ #define VERSION_MAJOR(v) (((v)>>16)&0xFF)
+ #define VERSION_MINOR(v) (((v)>>8)&0xFF)
+ #define VERSION_MICRO(v) (((v)>>0)&0xFF)
+
+ #define MINIMAL_APP_VERSION VERSION(MINIMAL_APP_VERSION_MAJOR, MINIMAL_APP_VERSION_MINOR, MINIMAL_APP_VERSION_MICRO)
+
void register_all(std::map<std::string, std::unique_ptr<device>> &registry);
#ifdef WITH_DEVICE_LEDGER
@@ -190,11 +203,16 @@ namespace hw {
/* ======================================================================= */
/* TRANSACTION */
/* ======================================================================= */
-
+ void generate_tx_proof(const crypto::hash &prefix_hash,
+ const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
+ crypto::signature &sig) override;
+
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;
+ rct::key genCommitmentMask(const rct::key &amount_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;
diff --git a/src/device/log.hpp b/src/device/log.hpp
index fb7ba1fb0..bfe6e9edc 100644
--- a/src/device/log.hpp
+++ b/src/device/log.hpp
@@ -40,6 +40,19 @@
namespace hw {
+ /* Note about debug:
+ * To debug Device you can def the following :
+ * #define DEBUG_HWDEVICE
+ * Activate debug mechanism:
+ * - Add more trace
+ * - All computation done by device are checked by default device.
+ * Required IODUMMYCRYPT_HWDEVICE or IONOCRYPT_HWDEVICE for fully working
+ * #define IODUMMYCRYPT_HWDEVICE 1
+ * - It assumes sensitive data encryption is is off on device side. a XOR with 0x55. This allow Ledger Class to make check on clear value
+ * #define IONOCRYPT_HWDEVICE 1
+ * - It assumes sensitive data encryption is off on device side.
+ */
+
void buffer_to_str(char *to_buff, size_t to_len, const char *buff, size_t len) ;
void log_hexbuffer(const std::string &msg, const char* buff, size_t len);
void log_message(const std::string &msg, const std::string &info );
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index 25571238e..e877c13ce 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -79,12 +79,12 @@ namespace
}
namespace rct {
- Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk)
+ Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk, hw::device &hwdev)
{
CHECK_AND_ASSERT_THROW_MES(amounts.size() == sk.size(), "Invalid amounts/sk sizes");
masks.resize(amounts.size());
for (size_t i = 0; i < masks.size(); ++i)
- masks[i] = genCommitmentMask(sk[i]);
+ masks[i] = hwdev.genCommitmentMask(sk[i]);
Bulletproof proof = bulletproof_PROVE(amounts, masks);
CHECK_AND_ASSERT_THROW_MES(proof.V.size() == amounts.size(), "V does not have the expected size");
C = proof.V;
@@ -804,7 +804,7 @@ namespace rct {
else
{
const epee::span<const key> keys{&amount_keys[0], amount_keys.size()};
- rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys));
+ rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys, hwdev));
#ifdef DBG
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
#endif
@@ -833,7 +833,7 @@ namespace rct {
else
{
const epee::span<const key> keys{&amount_keys[amounts_proved], batch_size};
- rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys));
+ rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys, hwdev));
#ifdef DBG
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
#endif
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 91a8f6348..25d40e5fb 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -6873,11 +6873,6 @@ bool simple_wallet::set_tx_key(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::get_tx_proof(const std::vector<std::string> &args)
{
- if (m_wallet->key_on_device() && m_wallet->get_account().get_device().get_type() != hw::device::TREZOR)
- {
- fail_msg_writer() << tr("command not supported by HW wallet");
- return true;
- }
if (args.size() != 2 && args.size() != 3)
{
PRINT_USAGE(USAGE_GET_TX_PROOF);
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index d8f3286d6..4679a1697 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -10430,7 +10430,7 @@ void wallet2::check_tx_key(const crypto::hash &txid, const crypto::secret_key &t
void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received) const
{
received = 0;
- hw::device &hwdev = m_account.get_device();
+
for (size_t n = 0; n < tx.vout.size(); ++n)
{
const cryptonote::txout_to_key* const out_key = boost::get<cryptonote::txout_to_key>(std::addressof(tx.vout[n].target));
@@ -10438,13 +10438,13 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
continue;
crypto::public_key derived_out_key;
- bool r = hwdev.derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key);
+ bool r = crypto::derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
bool found = out_key->key == derived_out_key;
crypto::key_derivation found_derivation = derivation;
if (!found && !additional_derivations.empty())
{
- r = hwdev.derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key);
+ r = crypto::derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
found = out_key->key == derived_out_key;
found_derivation = additional_derivations[n];
@@ -10460,9 +10460,9 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
else
{
crypto::secret_key scalar1;
- hwdev.derivation_to_scalar(found_derivation, n, scalar1);
+ crypto::derivation_to_scalar(found_derivation, n, scalar1);
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
- hwdev.ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2);
+ rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2);
const rct::key C = tx.rct_signatures.outPk[n].mask;
rct::key Ctmp;
THROW_WALLET_EXCEPTION_IF(sc_check(ecdh_info.mask.bytes) != 0, error::wallet_internal_error, "Bad ECDH input mask");
@@ -10573,6 +10573,8 @@ std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::ac
std::string wallet2::get_tx_proof(const cryptonote::transaction &tx, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message) const
{
+ hw::device &hwdev = m_account.get_device();
+ rct::key aP;
// determine if the address is found in the subaddress hash table (i.e. whether the proof is outbound or inbound)
const bool is_out = m_subaddresses.count(address.m_spend_public_key) == 0;
@@ -10591,30 +10593,34 @@ std::string wallet2::get_tx_proof(const cryptonote::transaction &tx, const crypt
shared_secret.resize(num_sigs);
sig.resize(num_sigs);
- shared_secret[0] = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(address.m_view_public_key), rct::sk2rct(tx_key)));
+ hwdev.scalarmultKey(aP, rct::pk2rct(address.m_view_public_key), rct::sk2rct(tx_key));
+ shared_secret[0] = rct::rct2pk(aP);
crypto::public_key tx_pub_key;
if (is_subaddress)
{
- tx_pub_key = rct2pk(rct::scalarmultKey(rct::pk2rct(address.m_spend_public_key), rct::sk2rct(tx_key)));
- crypto::generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[0], tx_key, sig[0]);
+ hwdev.scalarmultKey(aP, rct::pk2rct(address.m_spend_public_key), rct::sk2rct(tx_key));
+ tx_pub_key = rct2pk(aP);
+ hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[0], tx_key, sig[0]);
}
else
{
- crypto::secret_key_to_public_key(tx_key, tx_pub_key);
- crypto::generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[0], tx_key, sig[0]);
+ hwdev.secret_key_to_public_key(tx_key, tx_pub_key);
+ hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[0], tx_key, sig[0]);
}
for (size_t i = 1; i < num_sigs; ++i)
{
- shared_secret[i] = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(address.m_view_public_key), rct::sk2rct(additional_tx_keys[i - 1])));
+ hwdev.scalarmultKey(aP, rct::pk2rct(address.m_view_public_key), rct::sk2rct(additional_tx_keys[i - 1]));
+ shared_secret[i] = rct::rct2pk(aP);
if (is_subaddress)
{
- tx_pub_key = rct2pk(rct::scalarmultKey(rct::pk2rct(address.m_spend_public_key), rct::sk2rct(additional_tx_keys[i - 1])));
- crypto::generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
+ hwdev.scalarmultKey(aP, rct::pk2rct(address.m_spend_public_key), rct::sk2rct(additional_tx_keys[i - 1]));
+ tx_pub_key = rct2pk(aP);
+ hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
}
else
{
- crypto::secret_key_to_public_key(additional_tx_keys[i - 1], tx_pub_key);
- crypto::generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
+ hwdev.secret_key_to_public_key(additional_tx_keys[i - 1], tx_pub_key);
+ hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
}
}
sig_str = std::string("OutProofV1");
@@ -10630,25 +10636,27 @@ std::string wallet2::get_tx_proof(const cryptonote::transaction &tx, const crypt
sig.resize(num_sigs);
const crypto::secret_key& a = m_account.get_keys().m_view_secret_key;
- shared_secret[0] = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(tx_pub_key), rct::sk2rct(a)));
+ hwdev.scalarmultKey(aP, rct::pk2rct(tx_pub_key), rct::sk2rct(a));
+ shared_secret[0] = rct2pk(aP);
if (is_subaddress)
{
- crypto::generate_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, address.m_spend_public_key, shared_secret[0], a, sig[0]);
+ hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, address.m_spend_public_key, shared_secret[0], a, sig[0]);
}
else
{
- crypto::generate_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, shared_secret[0], a, sig[0]);
+ hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, shared_secret[0], a, sig[0]);
}
for (size_t i = 1; i < num_sigs; ++i)
{
- shared_secret[i] = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(additional_tx_pub_keys[i - 1]), rct::sk2rct(a)));
+ hwdev.scalarmultKey(aP,rct::pk2rct(additional_tx_pub_keys[i - 1]), rct::sk2rct(a));
+ shared_secret[i] = rct2pk(aP);
if (is_subaddress)
{
- crypto::generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], address.m_spend_public_key, shared_secret[i], a, sig[i]);
+ hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], address.m_spend_public_key, shared_secret[i], a, sig[i]);
}
else
{
- crypto::generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], boost::none, shared_secret[i], a, sig[i]);
+ hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], boost::none, shared_secret[i], a, sig[i]);
}
}
sig_str = std::string("InProofV1");