aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core
diff options
context:
space:
mode:
authorcslashm <cslashm@gmail.com>2018-02-20 17:01:27 +0100
committerCédric <cslashm@gmail.com>2018-03-04 12:54:53 +0100
commite745c1e38da8e54032660894bb2db0e9a49cccf2 (patch)
treefba40dea29a948b8a4904b4de189d4adc605ec6e /src/cryptonote_core
parentMerge pull request #3245 (diff)
downloadmonero-e745c1e38da8e54032660894bb2db0e9a49cccf2.tar.xz
Code modifications to integrate Ledger HW device into monero-wallet-cli.
The basic approach it to delegate all sensitive data (master key, secret ephemeral key, key derivation, ....) and related operations to the device. As device has low memory, it does not keep itself the values (except for view/spend keys) but once computed there are encrypted (with AES are equivalent) and return back to monero-wallet-cli. When they need to be manipulated by the device, they are decrypted on receive. Moreover, using the client for storing the value in encrypted form limits the modification in the client code. Those values are transfered from one C-structure to another one as previously. The code modification has been done with the wishes to be open to any other hardware wallet. To achieve that a C++ class hw::Device has been introduced. Two initial implementations are provided: the "default", which remaps all calls to initial Monero code, and the "Ledger", which delegates all calls to Ledger device.
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r--src/cryptonote_core/CMakeLists.txt1
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp39
2 files changed, 24 insertions, 16 deletions
diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt
index d8a21ae31..72844db66 100644
--- a/src/cryptonote_core/CMakeLists.txt
+++ b/src/cryptonote_core/CMakeLists.txt
@@ -61,6 +61,7 @@ target_link_libraries(cryptonote_core
blockchain_db
multisig
ringct
+ device
${Boost_DATE_TIME_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_SERIALIZATION_LIBRARY}
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index 4a10f7133..d641caf80 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -41,6 +41,7 @@ using namespace epee;
#include "crypto/hash.h"
#include "ringct/rctSigs.h"
#include "multisig/multisig.h"
+#include "device/device.hpp"
using namespace crypto;
@@ -194,6 +195,8 @@ namespace cryptonote
//---------------------------------------------------------------
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, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, 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, bool bulletproof, rct::multisig_out *msout)
{
+ hw::device &hwdev = sender_account_keys.get_device();
+
if (sources.empty())
{
LOG_ERROR("Empty sources");
@@ -232,7 +235,7 @@ namespace cryptonote
return false;
}
- if (!encrypt_payment_id(payment_id, view_key_pub, tx_key))
+ if (!encrypt_payment_id(payment_id, view_key_pub, tx_key, hwdev))
{
LOG_ERROR("Failed to encrypt payment id");
return false;
@@ -280,7 +283,7 @@ namespace cryptonote
keypair& in_ephemeral = in_contexts.back().in_ephemeral;
crypto::key_image img;
const auto& out_key = reinterpret_cast<const crypto::public_key&>(src_entr.outputs[src_entr.real_output].second.dest);
- if(!generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral, img))
+ if(!generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral,img, hwdev))
{
LOG_ERROR("Key image generation failed!");
return false;
@@ -338,11 +341,11 @@ namespace cryptonote
// if this is a single-destination transfer to a subaddress, we set the tx pubkey to R=s*D
if (num_stdaddresses == 0 && num_subaddresses == 1)
{
- txkey_pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(single_dest_subaddress.m_spend_public_key), rct::sk2rct(tx_key)));
+ txkey_pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(single_dest_subaddress.m_spend_public_key), rct::sk2rct(tx_key), hwdev));
}
else
{
- txkey_pub = rct::rct2pk(rct::scalarmultBase(rct::sk2rct(tx_key)));
+ txkey_pub = rct::rct2pk(rct::scalarmultBase(rct::sk2rct(tx_key), hwdev));
}
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key));
add_tx_pub_key_to_extra(tx, txkey_pub);
@@ -371,22 +374,22 @@ namespace cryptonote
{
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)));
+ additional_txkey.pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(dst_entr.addr.m_spend_public_key), rct::sk2rct(additional_txkey.sec),hwdev));
else
- additional_txkey.pub = rct::rct2pk(rct::scalarmultBase(rct::sk2rct(additional_txkey.sec)));
+ additional_txkey.pub = rct::rct2pk(rct::scalarmultBase(rct::sk2rct(additional_txkey.sec), hwdev));
}
bool r;
if (change_addr && dst_entr.addr == *change_addr)
{
// sending change to yourself; derivation = a*R
- r = crypto::generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation);
+ r = crypto::generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation, hwdev);
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 = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation);
+ r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation, hwdev);
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) << ")");
}
@@ -398,12 +401,14 @@ namespace cryptonote
if (tx.version > 1)
{
crypto::secret_key scalar1;
- crypto::derivation_to_scalar(derivation, output_index, scalar1);
+ crypto::derivation_to_scalar(derivation, output_index, scalar1, hwdev);
amount_keys.push_back(rct::sk2rct(scalar1));
}
- r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
+ r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key, hwdev);
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, output_index, amount_keys.back(), out_eph_public_key);
+
tx_out out;
out.amount = dst_entr.amount;
txout_to_key tk;
@@ -579,9 +584,9 @@ namespace cryptonote
get_transaction_prefix_hash(tx, tx_prefix_hash);
rct::ctkeyV outSk;
if (use_simple_rct)
- tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, msout ? &kLRki : NULL, msout, index, outSk, bulletproof);
+ tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, msout ? &kLRki : NULL, msout, index, outSk, bulletproof, hwdev);
else
- tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, msout ? &kLRki[0] : NULL, msout, sources[0].real_output, outSk, bulletproof); // same index assumption
+ tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, msout ? &kLRki[0] : NULL, msout, sources[0].real_output, outSk, bulletproof, hwdev); // same index assumption
CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout");
@@ -595,8 +600,8 @@ namespace cryptonote
//---------------------------------------------------------------
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, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, 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, bool bulletproof, rct::multisig_out *msout)
{
- keypair txkey = keypair::generate();
- tx_key = txkey.sec;
+ hw::device &hwdev = sender_account_keys.get_device();
+ hwdev.open_tx(tx_key);
// figure out if we need to make additional tx pubkeys
size_t num_stdaddresses = 0;
@@ -608,10 +613,12 @@ namespace cryptonote
{
additional_tx_keys.clear();
for (const auto &d: destinations)
- additional_tx_keys.push_back(keypair::generate().sec);
+ additional_tx_keys.push_back(keypair::generate(sender_account_keys.get_device()).sec);
}
- return construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, rct, bulletproof, msout);
+ bool r = construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, rct, bulletproof, msout);
+ hwdev.close_tx();
+ return r;
}
//---------------------------------------------------------------
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, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time)