diff options
Diffstat (limited to 'src/device/device_ledger.cpp')
-rw-r--r-- | src/device/device_ledger.cpp | 264 |
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 |