aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiccardo Spagni <ric@spagni.net>2019-03-04 14:58:45 +0200
committerRiccardo Spagni <ric@spagni.net>2019-03-04 14:58:45 +0200
commit8c53ac2dd156db87a0e7d1c354131cf158e364a3 (patch)
tree119c52f92f4b4eace8adf8a2baf437856fa8d206
parentMerge pull request #5128 (diff)
parentAdd support for V10 protocol with BulletProofV2 and short amount. (diff)
downloadmonero-8c53ac2dd156db87a0e7d1c354131cf158e364a3.tar.xz
Merge pull request #5132
2dbc487e Add support for V10 protocol with BulletProofV2 and short amount. (cslashm) 63cc02c0 Fix dummy decryption in debug mode (cslashm) f0e55ceb fix log namespace (cslashm) 460da140 New scheme key destination contrfol (cslashm)
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp45
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.h6
-rw-r--r--src/device/device.hpp10
-rw-r--r--src/device/device_default.cpp53
-rw-r--r--src/device/device_default.hpp9
-rw-r--r--src/device/device_ledger.cpp289
-rw-r--r--src/device/device_ledger.hpp19
-rw-r--r--src/device/log.cpp4
8 files changed, 314 insertions, 121 deletions
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index 0a04e0d38..c138c7854 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -405,49 +405,12 @@ namespace cryptonote
for(const tx_destination_entry& dst_entr: destinations)
{
CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount);
- crypto::key_derivation derivation;
crypto::public_key out_eph_public_key;
- // make additional tx pubkey if necessary
- keypair additional_txkey;
- if (need_additional_txkeys)
- {
- additional_txkey.sec = additional_tx_keys[output_index];
- if (dst_entr.is_subaddress)
- additional_txkey.pub = rct::rct2pk(hwdev.scalarmultKey(rct::pk2rct(dst_entr.addr.m_spend_public_key), rct::sk2rct(additional_txkey.sec)));
- else
- additional_txkey.pub = rct::rct2pk(hwdev.scalarmultBase(rct::sk2rct(additional_txkey.sec)));
- }
-
- bool r;
- if (change_addr && dst_entr.addr == *change_addr)
- {
- // sending change to yourself; derivation = a*R
- r = hwdev.generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation);
- CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")");
- }
- else
- {
- // sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
- r = hwdev.generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation);
- CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) << ")");
- }
-
- if (need_additional_txkeys)
- {
- additional_tx_public_keys.push_back(additional_txkey.pub);
- }
-
- if (tx.version > 1)
- {
- crypto::secret_key scalar1;
- hwdev.derivation_to_scalar(derivation, output_index, scalar1);
- amount_keys.push_back(rct::sk2rct(scalar1));
- }
- r = hwdev.derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
- CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")");
-
- hwdev.add_output_key_mapping(dst_entr.addr.m_view_public_key, dst_entr.addr.m_spend_public_key, dst_entr.is_subaddress, output_index, amount_keys.back(), out_eph_public_key);
+ hwdev.generate_output_ephemeral_keys(tx.version,sender_account_keys, txkey_pub, tx_key,
+ dst_entr, change_addr, output_index,
+ need_additional_txkeys, additional_tx_keys,
+ additional_tx_public_keys, amount_keys, out_eph_public_key);
tx_out out;
out.amount = dst_entr.amount;
diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h
index 85061668b..ad3297951 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.h
+++ b/src/cryptonote_core/cryptonote_tx_utils.h
@@ -97,6 +97,12 @@ namespace cryptonote
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time);
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL, bool shuffle_outs = true);
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL);
+ 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
diff --git a/src/device/device.hpp b/src/device/device.hpp
index bdb608907..408f64c8b 100644
--- a/src/device/device.hpp
+++ b/src/device/device.hpp
@@ -69,6 +69,7 @@ namespace cryptonote
struct account_public_address;
struct account_keys;
struct subaddress_index;
+ struct tx_destination_entry;
}
namespace hw {
@@ -211,9 +212,12 @@ namespace hw {
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;
- virtual bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index,
- const rct::key &amount_key, const crypto::public_key &out_eph_public_key) = 0;
-
+ virtual 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) = 0;
virtual bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) = 0;
virtual bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) = 0;
diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp
index cb2f4e266..fd15717a7 100644
--- a/src/device/device_default.cpp
+++ b/src/device/device_default.cpp
@@ -34,8 +34,10 @@
#include "int-util.h"
#include "cryptonote_basic/account.h"
#include "cryptonote_basic/subaddress_index.h"
+#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
@@ -278,10 +280,55 @@ namespace hw {
return true;
}
+ bool device_default::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 device_default::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index,
- const rct::key &amount_key, const crypto::public_key &out_eph_public_key) {
- return true;
+ crypto::key_derivation derivation;
+
+ // make additional tx pubkey if necessary
+ cryptonote::keypair additional_txkey;
+ if (need_additional_txkeys)
+ {
+ additional_txkey.sec = additional_tx_keys[output_index];
+ if (dst_entr.is_subaddress)
+ additional_txkey.pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(dst_entr.addr.m_spend_public_key), rct::sk2rct(additional_txkey.sec)));
+ else
+ additional_txkey.pub = rct::rct2pk(rct::scalarmultBase(rct::sk2rct(additional_txkey.sec)));
+ }
+
+ bool r;
+ if (change_addr && dst_entr.addr == *change_addr)
+ {
+ // sending change to yourself; derivation = a*R
+ r = generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation);
+ CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")");
+ }
+ else
+ {
+ // sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
+ r = generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation);
+ CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) << ")");
+ }
+
+ if (need_additional_txkeys)
+ {
+ additional_tx_public_keys.push_back(additional_txkey.pub);
+ }
+
+ if (tx_version > 1)
+ {
+ crypto::secret_key scalar1;
+ derivation_to_scalar(derivation, output_index, scalar1);
+ amount_keys.push_back(rct::sk2rct(scalar1));
+ }
+ r = derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
+ CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")");
+
+ return r;
}
bool device_default::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) {
diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp
index 54d159b11..04b9b4234 100644
--- a/src/device/device_default.hpp
+++ b/src/device/device_default.hpp
@@ -114,9 +114,12 @@ namespace hw {
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;
- bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index,
- const rct::key &amount_key, const crypto::public_key &out_eph_public_key) override;
-
+ bool generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key,
+ const cryptonote::tx_destination_entry &dst_entr, const boost::optional<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) override;
bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) override;
bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override;
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index 9daf62d37..1f91427f0 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -32,6 +32,7 @@
#include "ringct/rctOps.h"
#include "cryptonote_basic/account.h"
#include "cryptonote_basic/subaddress_index.h"
+#include "cryptonote_core/cryptonote_tx_utils.h"
#include <boost/thread/locks.hpp>
#include <boost/thread/lock_guard.hpp>
@@ -67,10 +68,12 @@ namespace hw {
/* === Keymap ==== */
/* ===================================================================== */
- ABPkeys::ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, const size_t real_output_index, const rct::key& P, const rct::key& AK) {
+ ABPkeys::ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, const bool is_change, const bool need_additional_txkeys, const size_t real_output_index, const rct::key& P, const rct::key& AK) {
Aout = A;
Bout = B;
is_subaddress = is_subaddr;
+ is_change_address = is_change;
+ additional_key = need_additional_txkeys;
index = real_output_index;
Pout = P;
AKout = AK;
@@ -80,6 +83,8 @@ namespace hw {
Aout = keys.Aout;
Bout = keys.Bout;
is_subaddress = keys.is_subaddress;
+ is_change_address = keys.is_change_address;
+ additional_key = keys.additional_key;
index = keys.index;
Pout = keys.Pout;
AKout = keys.AKout;
@@ -137,6 +142,8 @@ namespace hw {
static int device_id = 0;
+ #define PROTOCOL_VERSION 2
+
#define INS_NONE 0x00
#define INS_RESET 0x02
@@ -168,6 +175,7 @@ namespace hw {
#define INS_STEALTH 0x76
#define INS_BLIND 0x78
#define INS_UNBLIND 0x7A
+ #define INS_GEN_TXOUT_KEYS 0x7B
#define INS_VALIDATE 0x7C
#define INS_MLSAG 0x7E
#define INS_CLOSE_TX 0x80
@@ -268,7 +276,7 @@ namespace hw {
int device_ledger::set_command_header(unsigned char ins, unsigned char p1, unsigned char p2) {
reset_buffer();
int offset = 0;
- this->buffer_send[0] = 0x00;
+ this->buffer_send[0] = PROTOCOL_VERSION;
this->buffer_send[1] = ins;
this->buffer_send[2] = p1;
this->buffer_send[3] = p2;
@@ -508,11 +516,11 @@ namespace hw {
}
const std::size_t output_index_x = output_index;
crypto::public_key derived_pub_x;
- hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] pub ", pub_x.data, 32);
- hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] derivation", derivation_x.data, 32);
- hw::ledger::log_message ("derive_subaddress_public_key: [[IN]] index ", std::to_string((int)output_index_x));
+ log_hexbuffer("derive_subaddress_public_key: [[IN]] pub ", pub_x.data, 32);
+ log_hexbuffer("derive_subaddress_public_key: [[IN]] derivation", derivation_x.data, 32);
+ log_message ("derive_subaddress_public_key: [[IN]] index ", std::to_string((int)output_index_x));
this->controle_device->derive_subaddress_public_key(pub_x, derivation_x,output_index_x,derived_pub_x);
- hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32);
+ log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32);
#endif
if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
@@ -558,11 +566,11 @@ namespace hw {
const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys);
const cryptonote::subaddress_index index_x = index;
crypto::public_key D_x;
- hw::ledger::log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data,32);
- hw::ledger::log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_spend_secret_key", keys_x.m_spend_secret_key.data,32);
- hw::ledger::log_message ("get_subaddress_spend_public_key: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor));
+ log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data,32);
+ log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_spend_secret_key", keys_x.m_spend_secret_key.data,32);
+ log_message ("get_subaddress_spend_public_key: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor));
D_x = this->controle_device->get_subaddress_spend_public_key(keys_x, index_x);
- hw::ledger::log_hexbuffer("get_subaddress_spend_public_key: [[OUT]] derivation ", D_x.data, 32);
+ log_hexbuffer("get_subaddress_spend_public_key: [[OUT]] derivation ", D_x.data, 32);
#endif
if (index.is_zero()) {
@@ -609,14 +617,14 @@ namespace hw {
const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys);
const cryptonote::subaddress_index index_x = index;
cryptonote::account_public_address address_x;
- hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32);
- hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_view_public_key", keys_x.m_account_address.m_view_public_key.data, 32);
- hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32);
- hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_spend_public_key", keys_x.m_account_address.m_spend_public_key.data, 32);
- hw::ledger::log_message ("get_subaddress: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor));
+ log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32);
+ log_hexbuffer("get_subaddress: [[IN]] keys.m_view_public_key", keys_x.m_account_address.m_view_public_key.data, 32);
+ log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32);
+ log_hexbuffer("get_subaddress: [[IN]] keys.m_spend_public_key", keys_x.m_account_address.m_spend_public_key.data, 32);
+ log_message ("get_subaddress: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor));
address_x = this->controle_device->get_subaddress(keys_x, index_x);
- hw::ledger::log_hexbuffer("get_subaddress: [[OUT]] keys.m_view_public_key ", address_x.m_view_public_key.data, 32);
- hw::ledger::log_hexbuffer("get_subaddress: [[OUT]] keys.m_spend_public_key", address_x.m_spend_public_key.data, 32);
+ log_hexbuffer("get_subaddress: [[OUT]] keys.m_view_public_key ", address_x.m_view_public_key.data, 32);
+ log_hexbuffer("get_subaddress: [[OUT]] keys.m_spend_public_key", address_x.m_spend_public_key.data, 32);
#endif
if (index.is_zero()) {
@@ -652,10 +660,10 @@ namespace hw {
const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
const cryptonote::subaddress_index index_x = index;
crypto::secret_key sub_sec_x;
- hw::ledger::log_message ("get_subaddress_secret_key: [[IN]] index ", std::to_string(index.major)+"."+std::to_string(index.minor));
- hw::ledger::log_hexbuffer("get_subaddress_secret_key: [[IN]] sec ", sec_x.data, 32);
+ log_message ("get_subaddress_secret_key: [[IN]] index ", std::to_string(index.major)+"."+std::to_string(index.minor));
+ log_hexbuffer("get_subaddress_secret_key: [[IN]] sec ", sec_x.data, 32);
sub_sec_x = this->controle_device->get_subaddress_secret_key(sec_x, index_x);
- hw::ledger::log_hexbuffer("get_subaddress_secret_key: [[OUT]] sub_sec", sub_sec_x.data, 32);
+ log_hexbuffer("get_subaddress_secret_key: [[OUT]] sub_sec", sub_sec_x.data, 32);
#endif
int offset = set_command_header_noopt(INS_GET_SUBADDRESS_SECRET_KEY);
@@ -717,10 +725,10 @@ namespace hw {
const rct::key P_x = P;
const rct::key a_x = hw::ledger::decrypt(a);
rct::key aP_x;
- hw::ledger::log_hexbuffer("scalarmultKey: [[IN]] P ", (char*)P_x.bytes, 32);
- hw::ledger::log_hexbuffer("scalarmultKey: [[IN]] a ", (char*)a_x.bytes, 32);
+ log_hexbuffer("scalarmultKey: [[IN]] P ", (char*)P_x.bytes, 32);
+ log_hexbuffer("scalarmultKey: [[IN]] a ", (char*)a_x.bytes, 32);
this->controle_device->scalarmultKey(aP_x, P_x, a_x);
- hw::ledger::log_hexbuffer("scalarmultKey: [[OUT]] aP", (char*)aP_x.bytes, 32);
+ log_hexbuffer("scalarmultKey: [[OUT]] aP", (char*)aP_x.bytes, 32);
#endif
int offset = set_command_header_noopt(INS_SECRET_SCAL_MUL_KEY);
@@ -752,9 +760,9 @@ namespace hw {
#ifdef DEBUG_HWDEVICE
const rct::key a_x = hw::ledger::decrypt(a);
rct::key aG_x;
- hw::ledger::log_hexbuffer("scalarmultKey: [[IN]] a ", (char*)a_x.bytes, 32);
+ log_hexbuffer("scalarmultKey: [[IN]] a ", (char*)a_x.bytes, 32);
this->controle_device->scalarmultBase(aG_x, a_x);
- hw::ledger::log_hexbuffer("scalarmultKey: [[OUT]] aG", (char*)aG_x.bytes, 32);
+ log_hexbuffer("scalarmultKey: [[OUT]] aG", (char*)aG_x.bytes, 32);
#endif
int offset = set_command_header_noopt(INS_SECRET_SCAL_MUL_BASE);
@@ -845,10 +853,10 @@ namespace hw {
const crypto::public_key pub_x = pub;
const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
crypto::key_derivation derivation_x;
- hw::ledger::log_hexbuffer("generate_key_derivation: [[IN]] pub ", pub_x.data, 32);
- hw::ledger::log_hexbuffer("generate_key_derivation: [[IN]] sec ", sec_x.data, 32);
+ log_hexbuffer("generate_key_derivation: [[IN]] pub ", pub_x.data, 32);
+ log_hexbuffer("generate_key_derivation: [[IN]] sec ", sec_x.data, 32);
this->controle_device->generate_key_derivation(pub_x, sec_x, derivation_x);
- hw::ledger::log_hexbuffer("generate_key_derivation: [[OUT]] derivation", derivation_x.data, 32);
+ log_hexbuffer("generate_key_derivation: [[OUT]] derivation", derivation_x.data, 32);
#endif
if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
@@ -914,10 +922,10 @@ namespace hw {
const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
const size_t output_index_x = output_index;
crypto::ec_scalar res_x;
- hw::ledger::log_hexbuffer("derivation_to_scalar: [[IN]] derivation ", derivation_x.data, 32);
- hw::ledger::log_message ("derivation_to_scalar: [[IN]] output_index ", std::to_string(output_index_x));
+ log_hexbuffer("derivation_to_scalar: [[IN]] derivation ", derivation_x.data, 32);
+ log_message ("derivation_to_scalar: [[IN]] output_index ", std::to_string(output_index_x));
this->controle_device->derivation_to_scalar(derivation_x, output_index_x, res_x);
- hw::ledger::log_hexbuffer("derivation_to_scalar: [[OUT]] res ", res_x.data, 32);
+ log_hexbuffer("derivation_to_scalar: [[OUT]] res ", res_x.data, 32);
#endif
int offset = set_command_header_noopt(INS_DERIVATION_TO_SCALAR);
@@ -954,11 +962,11 @@ namespace hw {
const std::size_t output_index_x = output_index;
const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
crypto::secret_key derived_sec_x;
- hw::ledger::log_hexbuffer("derive_secret_key: [[IN]] derivation ", derivation_x.data, 32);
- hw::ledger::log_message ("derive_secret_key: [[IN]] index ", std::to_string(output_index_x));
- hw::ledger::log_hexbuffer("derive_secret_key: [[IN]] sec ", sec_x.data, 32);
+ log_hexbuffer("derive_secret_key: [[IN]] derivation ", derivation_x.data, 32);
+ log_message ("derive_secret_key: [[IN]] index ", std::to_string(output_index_x));
+ log_hexbuffer("derive_secret_key: [[IN]] sec ", sec_x.data, 32);
this->controle_device->derive_secret_key(derivation_x, output_index_x, sec_x, derived_sec_x);
- hw::ledger::log_hexbuffer("derive_secret_key: [[OUT]] derived_sec", derived_sec_x.data, 32);
+ log_hexbuffer("derive_secret_key: [[OUT]] derived_sec", derived_sec_x.data, 32);
#endif
int offset = set_command_header_noopt(INS_DERIVE_SECRET_KEY);
@@ -998,11 +1006,11 @@ namespace hw {
const std::size_t output_index_x = output_index;
const crypto::public_key pub_x = pub;
crypto::public_key derived_pub_x;
- hw::ledger::log_hexbuffer("derive_public_key: [[IN]] derivation ", derivation_x.data, 32);
- hw::ledger::log_message ("derive_public_key: [[IN]] output_index", std::to_string(output_index_x));
- hw::ledger::log_hexbuffer("derive_public_key: [[IN]] pub ", pub_x.data, 32);
+ log_hexbuffer("derive_public_key: [[IN]] derivation ", derivation_x.data, 32);
+ log_message ("derive_public_key: [[IN]] output_index", std::to_string(output_index_x));
+ log_hexbuffer("derive_public_key: [[IN]] pub ", pub_x.data, 32);
this->controle_device->derive_public_key(derivation_x, output_index_x, pub_x, derived_pub_x);
- hw::ledger::log_hexbuffer("derive_public_key: [[OUT]] derived_pub ", derived_pub_x.data, 32);
+ log_hexbuffer("derive_public_key: [[OUT]] derived_pub ", derived_pub_x.data, 32);
#endif
int offset = set_command_header_noopt(INS_DERIVE_PUBLIC_KEY);
@@ -1039,11 +1047,11 @@ namespace hw {
#ifdef DEBUG_HWDEVICE
const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
crypto::public_key pub_x;
- hw::ledger::log_hexbuffer("secret_key_to_public_key: [[IN]] sec ", sec_x.data, 32);
+ log_hexbuffer("secret_key_to_public_key: [[IN]] sec ", sec_x.data, 32);
bool rc = this->controle_device->secret_key_to_public_key(sec_x, pub_x);
- hw::ledger::log_hexbuffer("secret_key_to_public_key: [[OUT]] pub", pub_x.data, 32);
+ log_hexbuffer("secret_key_to_public_key: [[OUT]] pub", pub_x.data, 32);
if (!rc){
- hw::ledger::log_message("secret_key_to_public_key", "secret_key rejected");
+ log_message("secret_key_to_public_key", "secret_key rejected");
}
#endif
@@ -1073,10 +1081,10 @@ namespace hw {
const crypto::public_key pub_x = pub;
const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
crypto::key_image image_x;
- hw::ledger::log_hexbuffer("generate_key_image: [[IN]] pub ", pub_x.data, 32);
- hw::ledger::log_hexbuffer("generate_key_image: [[IN]] sec ", sec_x.data, 32);
+ log_hexbuffer("generate_key_image: [[IN]] pub ", pub_x.data, 32);
+ log_hexbuffer("generate_key_image: [[IN]] sec ", sec_x.data, 32);
this->controle_device->generate_key_image(pub_x, sec_x, image_x);
- hw::ledger::log_hexbuffer("generate_key_image: [[OUT]] image ", image_x.data, 32);
+ log_hexbuffer("generate_key_image: [[OUT]] image ", image_x.data, 32);
#endif
int offset = set_command_header_noopt(INS_GEN_KEY_IMAGE);
@@ -1160,10 +1168,139 @@ namespace hw {
return true;
}
- bool device_ledger::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index,
- const rct::key &amount_key, const crypto::public_key &out_eph_public_key) {
- AUTO_LOCK_CMD();
- key_map.add(ABPkeys(rct::pk2rct(Aout),rct::pk2rct(Bout), is_subaddress, real_output_index, rct::pk2rct(out_eph_public_key), amount_key));
+
+ bool device_ledger::generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key,
+ const cryptonote::tx_destination_entry &dst_entr, const boost::optional<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) {
+ AUTO_LOCK_CMD();
+
+ #ifdef DEBUG_HWDEVICE
+ const size_t &tx_version_x = tx_version;
+ const cryptonote::account_keys sender_account_keys_x = sender_account_keys;
+ memmove((void*)sender_account_keys_x.m_view_secret_key.data, dbg_viewkey.data, 32);
+
+ const crypto::public_key &txkey_pub_x = txkey_pub;
+ const crypto::secret_key &tx_key_x = tx_key;
+ const cryptonote::tx_destination_entry &dst_entr_x = dst_entr;
+ const boost::optional<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;
+ 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;
+ this->controle_device->generate_output_ephemeral_keys(tx_version_x, sender_account_keys_x, txkey_pub_x, tx_key_x, dst_entr_x, change_addr_x, output_index_x, need_additional_txkeys_x, additional_tx_keys_x,
+ additional_tx_public_keys_x, amount_keys_x, out_eph_public_key_x);
+ #endif
+
+ // make additional tx pubkey if necessary
+ cryptonote::keypair additional_txkey;
+ if (need_additional_txkeys) {
+ additional_txkey.sec = additional_tx_keys[output_index];
+ }
+
+ //compute derivation, out_eph_public_key, and amount key in one shot on device, to ensure checkable link
+ const crypto::secret_key *sec;
+ bool is_change;
+
+ if (change_addr && dst_entr.addr == *change_addr)
+ {
+ // sending change to yourself; derivation = a*R
+ is_change = true;
+ sec = &sender_account_keys.m_view_secret_key;
+ }
+ else
+ {
+ is_change = false;
+ if (dst_entr.is_subaddress && need_additional_txkeys) {
+ sec = &additional_txkey.sec;
+ } else {
+ sec = &tx_key;
+ }
+ }
+
+ int offset = set_command_header_noopt(INS_GEN_TXOUT_KEYS);
+ //tx_version
+ this->buffer_send[offset+0] = tx_version>>24;
+ this->buffer_send[offset+1] = tx_version>>16;
+ this->buffer_send[offset+2] = tx_version>>8;
+ this->buffer_send[offset+3] = tx_version>>0;
+ offset += 4;
+ //tx_sec
+ memmove(&this->buffer_send[offset], sec->data, 32);
+ offset += 32;
+ //Aout
+ memmove(&this->buffer_send[offset], dst_entr.addr.m_view_public_key.data, 32);
+ offset += 32;
+ //Bout
+ memmove(&this->buffer_send[offset], dst_entr.addr.m_spend_public_key.data, 32);
+ offset += 32;
+ //output index
+ this->buffer_send[offset+0] = output_index>>24;
+ this->buffer_send[offset+1] = output_index>>16;
+ this->buffer_send[offset+2] = output_index>>8;
+ this->buffer_send[offset+3] = output_index>>0;
+ offset += 4;
+ //is_change,
+ this->buffer_send[offset] = is_change;
+ offset++;
+ //is_subaddress
+ this->buffer_send[offset] = dst_entr.is_subaddress;
+ offset++;
+ //need_additional_key
+ this->buffer_send[offset] = need_additional_txkeys;
+ offset++;
+
+ this->buffer_send[4] = offset-5;
+ this->length_send = offset;
+ this->exchange();
+
+ offset = 0;
+ unsigned int recv_len = this->length_recv;
+ if (need_additional_txkeys)
+ {
+ ASSERT_X(recv_len>=32, "Not enought data from device");
+ memmove(additional_txkey.pub.data, &this->buffer_recv[offset], 32);
+ additional_tx_public_keys.push_back(additional_txkey.pub);
+ offset += 32;
+ recv_len -= 32;
+ }
+ if (tx_version > 1)
+ {
+ ASSERT_X(recv_len>=32, "Not enought data from device");
+ crypto::secret_key scalar1;
+ memmove(scalar1.data, &this->buffer_recv[offset],32);
+ amount_keys.push_back(rct::sk2rct(scalar1));
+ offset += 32;
+ recv_len -= 32;
+ }
+ ASSERT_X(recv_len>=32, "Not enought data from device");
+ memmove(out_eph_public_key.data, &this->buffer_recv[offset], 32);
+ recv_len -= 32;
+
+ // add ABPkeys
+ this->add_output_key_mapping(dst_entr.addr.m_view_public_key, dst_entr.addr.m_spend_public_key, dst_entr.is_subaddress, is_change,
+ need_additional_txkeys, output_index,
+ amount_keys.back(), out_eph_public_key);
+
+ #ifdef DEBUG_HWDEVICE
+ hw::ledger::check32("generate_output_ephemeral_keys", "amount_key", (const char*)amount_keys_x.back().bytes, (const char*)hw::ledger::decrypt(amount_keys.back()).bytes);
+ if (need_additional_txkeys) {
+ hw::ledger::check32("generate_output_ephemeral_keys", "additional_tx_key", additional_tx_keys_x.back().data, additional_tx_keys.back().data);
+ }
+ hw::ledger::check32("generate_output_ephemeral_keys", "out_eph_public_key", out_eph_public_key_x.data, out_eph_public_key.data);
+ #endif
+
+ return true;
+ }
+
+ bool device_ledger::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const bool is_change,
+ const bool need_additional, const size_t real_output_index,
+ const rct::key &amount_key, const crypto::public_key &out_eph_public_key) {
+ key_map.add(ABPkeys(rct::pk2rct(Aout),rct::pk2rct(Bout), is_subaddress, is_change, need_additional, real_output_index, rct::pk2rct(out_eph_public_key), amount_key));
return true;
}
@@ -1176,7 +1313,10 @@ namespace hw {
this->controle_device->ecdhEncode(unmasked_x, AKout_x, short_amount);
#endif
- int offset = set_command_header_noopt(INS_BLIND);
+ int offset = set_command_header(INS_BLIND);
+ //options
+ this->buffer_send[offset] = short_amount?0x02:0x00;
+ offset += 1;
// AKout
memmove(this->buffer_send+offset, AKout.bytes, 32);
offset += 32;
@@ -1198,7 +1338,7 @@ namespace hw {
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);
- hw::ledger::log_hexbuffer("Blind AKV input", (char*)&this->buffer_recv[64], 3*32);
+ log_hexbuffer("Blind AKV input", (char*)&this->buffer_recv[64], 3*32);
#endif
return true;
@@ -1213,8 +1353,10 @@ namespace hw {
this->controle_device->ecdhDecode(masked_x, AKout_x, short_amount);
#endif
- int offset = set_command_header_noopt(INS_UNBLIND);
-
+ int offset = set_command_header(INS_UNBLIND);
+ //options
+ this->buffer_send[offset] = short_amount?0x02:0x00;
+ offset += 1;
// AKout
memmove(this->buffer_send+offset, AKout.bytes, 32);
offset += 32;
@@ -1310,7 +1452,11 @@ namespace hw {
// ====== Aout, Bout, AKout, C, v, k ======
kv_offset = data_offset;
- C_offset = kv_offset+ (32*2)*outputs_size;
+ if (type==rct::RCTTypeBulletproof2) {
+ C_offset = kv_offset+ (8)*outputs_size;
+ } else {
+ C_offset = kv_offset+ (32+32)*outputs_size;
+ }
for ( i = 0; i < outputs_size; i++) {
ABPkeys outKeys;
bool found;
@@ -1323,11 +1469,15 @@ 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)?0x02:0x00;
offset += 1;
if (found) {
//is_subaddress
this->buffer_send[offset] = outKeys.is_subaddress;
offset++;
+ //is_change_address
+ this->buffer_send[offset] = outKeys.is_change_address;
+ offset++;
//Aout
memmove(this->buffer_send+offset, outKeys.Aout.bytes, 32);
offset+=32;
@@ -1339,27 +1489,38 @@ namespace hw {
offset+=32;
} else {
// dummy: is_subaddress Aout Bout AKout
- offset += 1+32*3;
+ offset += 2+32*3;
}
//C
memmove(this->buffer_send+offset, data+C_offset,32);
offset += 32;
C_offset += 32;
- //k
- memmove(this->buffer_send+offset, data+kv_offset,32);
- offset += 32;
- //v
- kv_offset += 32;
- memmove(this->buffer_send+offset, data+kv_offset,32);
- offset += 32;
- kv_offset += 32;
+ if (type==rct::RCTTypeBulletproof2) {
+ //k
+ memset(this->buffer_send+offset, 0, 32);
+ offset += 32;
+ //v
+ memset(this->buffer_send+offset, 0, 32);
+ memmove(this->buffer_send+offset, data+kv_offset,8);
+ offset += 32;
+ kv_offset += 8;
+ } else {
+ //k
+ memmove(this->buffer_send+offset, data+kv_offset,32);
+ offset += 32;
+ kv_offset += 32;
+ //v
+ memmove(this->buffer_send+offset, data+kv_offset,32);
+ offset += 32;
+ kv_offset += 32;
+ }
this->buffer_send[4] = offset-5;
this->length_send = offset;
// check transaction user input
CHECK_AND_ASSERT_THROW_MES(this->exchange_wait_on_input() == 0, "Transaction denied on device.");
#ifdef DEBUG_HWDEVICE
- hw::ledger::log_hexbuffer("Prehash AKV input", (char*)&this->buffer_recv[64], 3*32);
+ log_hexbuffer("Prehash AKV input", (char*)&this->buffer_recv[64], 3*32);
#endif
}
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index 584f1e096..3f470ee7c 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -56,12 +56,14 @@ namespace hw {
rct::key Aout;
rct::key Bout;
bool is_subaddress;
+ bool is_change_address;
+ bool additional_key ;
size_t index;
rct::key Pout;
rct::key AKout;
- ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, size_t index, const rct::key& P,const rct::key& AK);
+ ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, bool is_subaddress, bool is_change_address, size_t index, const rct::key& P,const rct::key& AK);
ABPkeys(const ABPkeys& keys) ;
- ABPkeys() {index=0;is_subaddress=false;}
+ ABPkeys() {index=0;is_subaddress=false;is_subaddress=false;is_change_address=false;}
};
class Keymap {
@@ -105,7 +107,9 @@ namespace hw {
device_mode mode;
// map public destination key to ephemeral destination key
Keymap key_map;
-
+ bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const bool is_change,
+ const bool need_additional, const size_t real_output_index,
+ const rct::key &amount_key, const crypto::public_key &out_eph_public_key);
// To speed up blockchain parsing the view key maybe handle here.
crypto::secret_key viewkey;
bool has_view_key;
@@ -194,9 +198,12 @@ namespace hw {
bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_format) override;
bool ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_format) override;
- bool add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index,
- const rct::key &amount_key, const crypto::public_key &out_eph_public_key) override;
-
+ bool generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key,
+ const cryptonote::tx_destination_entry &dst_entr, const boost::optional<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) override;
bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) override;
bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override;
diff --git a/src/device/log.cpp b/src/device/log.cpp
index c9d3b551b..87505798b 100644
--- a/src/device/log.cpp
+++ b/src/device/log.cpp
@@ -66,7 +66,7 @@ namespace hw {
void decrypt(char* buf, size_t len) {
- #ifdef IODUMMYCRYPT_HWDEVICE
+ #if defined(IODUMMYCRYPT_HWDEVICE) || defined(IONOCRYPT_HWDEVICE)
size_t i;
if (len == 32) {
//view key?
@@ -86,11 +86,13 @@ namespace hw {
return;
}
}
+ #if defined(IODUMMYCRYPT_HWDEVICE)
//std decrypt: XOR.55h
for (i = 0; i<len;i++) {
buf[i] ^= 0x55;
}
#endif
+ #endif
}
crypto::key_derivation decrypt(const crypto::key_derivation &derivation) {