aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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");