aboutsummaryrefslogtreecommitdiff
path: root/src/device/device_ledger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/device/device_ledger.cpp')
-rw-r--r--src/device/device_ledger.cpp264
1 files changed, 211 insertions, 53 deletions
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