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)
This commit is contained in:
Riccardo Spagni 2019-03-04 14:58:45 +02:00
commit 8c53ac2dd1
No known key found for this signature in database
GPG Key ID: 55432DF31CCD4FCD
8 changed files with 314 additions and 121 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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
}

View File

@ -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;

View File

@ -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) {