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.cpp266
1 files changed, 175 insertions, 91 deletions
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index 15fe560d1..49f54e5a5 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -65,6 +65,41 @@ namespace hw {
#endif
/* ===================================================================== */
+ /* === hmacmap ==== */
+ /* ===================================================================== */
+
+
+ SecHMAC::SecHMAC(const uint8_t s[32], const uint8_t h[32]) {
+ memcpy(this->sec, s, 32);
+ memcpy(this->hmac, h, 32);
+ }
+
+ void HMACmap::find_mac(const uint8_t sec[32], uint8_t hmac[32]) {
+ size_t sz = hmacs.size();
+ log_hexbuffer("find_mac: lookup for ", (char*)sec,32);
+ for (size_t i=0; i<sz; i++) {
+ log_hexbuffer("find_mac: - try ",(char*)hmacs[i].sec,32);
+ if (memcmp(sec, hmacs[i].sec, 32) == 0) {
+ memcpy(hmac, hmacs[i].hmac, 32);
+ log_hexbuffer("find_mac: - found ",(char*)hmacs[i].hmac,32);
+ return;
+ }
+
+ }
+ throw std::runtime_error("Protocol error: try to send untrusted secret");
+ }
+
+ void HMACmap::add_mac(const uint8_t sec[32], const uint8_t hmac[32]) {
+ log_hexbuffer("add_mac: sec ", (char*)sec,32);
+ log_hexbuffer("add_mac: hmac ", (char*)hmac,32);
+ hmacs.push_back(SecHMAC(sec,hmac));
+ }
+
+ void HMACmap::clear() {
+ hmacs.clear();
+ }
+
+ /* ===================================================================== */
/* === Keymap ==== */
/* ===================================================================== */
@@ -162,9 +197,11 @@ namespace hw {
#define INS_RESET 0x02
#define INS_GET_KEY 0x20
+ #define INS_DISPLAY_ADDRESS 0x21
#define INS_PUT_KEY 0x22
#define INS_GET_CHACHA8_PREKEY 0x24
#define INS_VERIFY_KEY 0x26
+ #define INS_MANAGE_SEEDWORDS 0x28
#define INS_SECRET_KEY_TO_PUBLIC_KEY 0x30
#define INS_GEN_KEY_DERIVATION 0x32
@@ -205,6 +242,7 @@ namespace hw {
this->reset_buffer();
this->mode = NONE;
this->has_view_key = false;
+ this->tx_in_progress = false;
MDEBUG( "Device "<<this->id <<" Created");
}
@@ -317,6 +355,30 @@ namespace hw {
}
}
+ void device_ledger::send_secret(const unsigned char sec[32], int &offset) {
+ MDEBUG("send_secret: " << this->tx_in_progress);
+ ASSERT_X(offset + 32 <= BUFFER_SEND_SIZE, "send_secret: out of bounds write (secret)");
+ memmove(this->buffer_send+offset, sec, 32);
+ offset +=32;
+ if (this->tx_in_progress) {
+ ASSERT_X(offset + 32 <= BUFFER_SEND_SIZE, "send_secret: out of bounds write (mac)");
+ this->hmac_map.find_mac((uint8_t*)sec, this->buffer_send+offset);
+ offset += 32;
+ }
+ }
+
+ void device_ledger::receive_secret(unsigned char sec[32], int &offset) {
+ MDEBUG("receive_secret: " << this->tx_in_progress);
+ ASSERT_X(offset + 32 <= BUFFER_RECV_SIZE, "receive_secret: out of bounds read (secret)");
+ memmove(sec, this->buffer_recv+offset, 32);
+ offset += 32;
+ if (this->tx_in_progress) {
+ ASSERT_X(offset + 32 <= BUFFER_RECV_SIZE, "receive_secret: out of bounds read (mac)");
+ this->hmac_map.add_mac((uint8_t*)sec, this->buffer_recv+offset);
+ offset += 32;
+ }
+ }
+
bool device_ledger::reset() {
reset_buffer();
int offset = set_command_header_noopt(INS_RESET);
@@ -418,10 +480,10 @@ namespace hw {
#ifdef DEBUG_HWDEVICE
cryptonote::account_public_address pubkey;
this->get_public_address(pubkey);
+ #endif
crypto::secret_key vkey;
crypto::secret_key skey;
this->get_secret_keys(vkey,skey);
- #endif
return true;
}
@@ -509,6 +571,7 @@ namespace hw {
}
#ifdef DEBUG_HWDEVICE
+ send_simple(INS_GET_KEY, 0x04);
memmove(dbg_viewkey.data, this->buffer_recv+0, 32);
memmove(dbg_spendkey.data, this->buffer_recv+32, 32);
#endif
@@ -538,6 +601,27 @@ namespace hw {
return true;
}
+ void device_ledger::display_address(const cryptonote::subaddress_index& index, const boost::optional<crypto::hash8> &payment_id) {
+ AUTO_LOCK_CMD();
+
+ int offset = set_command_header_noopt(INS_DISPLAY_ADDRESS, payment_id?1:0);
+ //index
+ memmove(this->buffer_send+offset, &index, sizeof(cryptonote::subaddress_index));
+ offset +=8 ;
+
+ //payment ID
+ if (payment_id) {
+ memmove(this->buffer_send+offset, (*payment_id).data, 8);
+ } else {
+ memset(this->buffer_send+offset, 0, 8);
+ }
+ offset +=8;
+
+ this->buffer_send[4] = offset-5;
+ this->length_send = offset;
+ CHECK_AND_ASSERT_THROW_MES(this->exchange_wait_on_input() == 0, "Timeout/Error on display address.");
+ }
+
/* ======================================================================= */
/* SUB ADDRESS */
/* ======================================================================= */
@@ -573,8 +657,7 @@ namespace hw {
memmove(this->buffer_send+offset, pub.data, 32);
offset += 32;
//derivation
- memmove(this->buffer_send+offset, derivation.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)derivation.data, offset);
//index
this->buffer_send[offset+0] = output_index>>24;
this->buffer_send[offset+1] = output_index>>16;
@@ -706,8 +789,7 @@ namespace hw {
int offset = set_command_header_noopt(INS_GET_SUBADDRESS_SECRET_KEY);
//sec
- memmove(this->buffer_send+offset, sec.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)sec.data, offset);
//index
static_assert(sizeof(cryptonote::subaddress_index) == 8, "cryptonote::subaddress_index shall be 8 bytes length");
memmove(this->buffer_send+offset, &index, sizeof(cryptonote::subaddress_index));
@@ -717,7 +799,8 @@ namespace hw {
this->length_send = offset;
this->exchange();
- memmove(sub_sec.data, &this->buffer_recv[0], 32);
+ offset = 0;
+ this->receive_secret((unsigned char*)sub_sec.data, offset);
#ifdef DEBUG_HWDEVICE
crypto::secret_key sub_sec_clear = hw::ledger::decrypt(sub_sec);
@@ -737,8 +820,7 @@ namespace hw {
offset = set_command_header_noopt(INS_VERIFY_KEY);
//sec
- memmove(this->buffer_send+offset, secret_key.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)secret_key.data, offset);
//pub
memmove(this->buffer_send+offset, public_key.data, 32);
offset += 32;
@@ -774,9 +856,7 @@ namespace hw {
memmove(this->buffer_send+offset, P.bytes, 32);
offset += 32;
//sec
- memmove(this->buffer_send+offset, a.bytes, 32);
- offset += 32;
-
+ this->send_secret(a.bytes, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
@@ -805,8 +885,7 @@ namespace hw {
int offset = set_command_header_noopt(INS_SECRET_SCAL_MUL_BASE);
//sec
- memmove(this->buffer_send+offset, a.bytes, 32);
- offset += 32;
+ this->send_secret(a.bytes, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
@@ -824,6 +903,7 @@ namespace hw {
bool device_ledger::sc_secret_add( crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) {
AUTO_LOCK_CMD();
+ int offset;
#ifdef DEBUG_HWDEVICE
const crypto::secret_key a_x = hw::ledger::decrypt(a);
@@ -836,20 +916,19 @@ namespace hw {
log_hexbuffer("sc_secret_add: [[OUT]] aG", (char*)r_x.data, 32);
#endif
- int offset = set_command_header_noopt(INS_SECRET_KEY_ADD);
+ offset = set_command_header_noopt(INS_SECRET_KEY_ADD);
//sec key
- memmove(this->buffer_send+offset, a.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)a.data, offset);
//sec key
- memmove(this->buffer_send+offset, b.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)b.data, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
this->exchange();
- //pub key
- memmove(r.data, &this->buffer_recv[0], 32);
+ //sec key
+ offset = 0;
+ this->receive_secret((unsigned char*)r.data, offset);
#ifdef DEBUG_HWDEVICE
crypto::secret_key r_clear = hw::ledger::decrypt(r);
@@ -861,6 +940,8 @@ namespace hw {
crypto::secret_key device_ledger::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover) {
AUTO_LOCK_CMD();
+ int offset;
+
if (recover) {
throw std::runtime_error("device generate key does not support recover");
}
@@ -877,9 +958,11 @@ namespace hw {
send_simple(INS_GENERATE_KEYPAIR);
+ offset = 0;
//pub key
memmove(pub.data, &this->buffer_recv[0], 32);
- memmove(sec.data, &this->buffer_recv[32], 32);
+ offset += 32;
+ this->receive_secret((unsigned char*)sec.data, offset);
#ifdef DEBUG_HWDEVICE
crypto::secret_key sec_clear = hw::ledger::decrypt(sec);
@@ -922,15 +1005,16 @@ namespace hw {
memmove(this->buffer_send+offset, pub.data, 32);
offset += 32;
//sec
- memmove(this->buffer_send+offset, sec.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)sec.data, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
this->exchange();
+ offset = 0;
//derivattion data
- memmove(derivation.data, &this->buffer_recv[0], 32);
+ this->receive_secret((unsigned char*)derivation.data, offset);
+
r = true;
}
#ifdef DEBUG_HWDEVICE
@@ -978,9 +1062,9 @@ namespace hw {
#endif
int offset = set_command_header_noopt(INS_DERIVATION_TO_SCALAR);
- //derivattion
- memmove(this->buffer_send+offset, derivation.data, 32);
- offset += 32;
+ //derivation
+ this->send_secret((unsigned char*)derivation.data, offset);
+
//index
this->buffer_send[offset+0] = output_index>>24;
this->buffer_send[offset+1] = output_index>>16;
@@ -992,8 +1076,9 @@ namespace hw {
this->length_send = offset;
this->exchange();
- //derivattion data
- memmove(res.data, &this->buffer_recv[0], 32);
+ //derivation data
+ offset = 0;
+ this->receive_secret((unsigned char*)res.data, offset);
#ifdef DEBUG_HWDEVICE
crypto::ec_scalar res_clear = hw::ledger::decrypt(res);
@@ -1020,8 +1105,7 @@ namespace hw {
int offset = set_command_header_noopt(INS_DERIVE_SECRET_KEY);
//derivation
- memmove(this->buffer_send+offset, derivation.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)derivation.data, offset);
//index
this->buffer_send[offset+0] = output_index>>24;
this->buffer_send[offset+1] = output_index>>16;
@@ -1029,15 +1113,15 @@ namespace hw {
this->buffer_send[offset+3] = output_index>>0;
offset += 4;
//sec
- memmove(this->buffer_send+offset, sec.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)sec.data, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
this->exchange();
- //pub key
- memmove(derived_sec.data, &this->buffer_recv[0], 32);
+ offset = 0;
+ //sec key
+ this->receive_secret((unsigned char*)derived_sec.data, offset);
#ifdef DEBUG_HWDEVICE
crypto::secret_key derived_sec_clear = hw::ledger::decrypt(derived_sec);
@@ -1064,8 +1148,7 @@ namespace hw {
int offset = set_command_header_noopt(INS_DERIVE_PUBLIC_KEY);
//derivation
- memmove(this->buffer_send+offset, derivation.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)derivation.data, offset);
//index
this->buffer_send[offset+0] = output_index>>24;
this->buffer_send[offset+1] = output_index>>16;
@@ -1106,8 +1189,7 @@ namespace hw {
int offset = set_command_header_noopt(INS_SECRET_KEY_TO_PUBLIC_KEY);
//sec key
- memmove(this->buffer_send+offset, sec.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)sec.data, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
@@ -1141,8 +1223,7 @@ namespace hw {
memmove(this->buffer_send+offset, pub.data, 32);
offset += 32;
//sec
- memmove(this->buffer_send+offset, sec.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)sec.data, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
@@ -1211,8 +1292,7 @@ namespace hw {
memmove(&this->buffer_send[offset], D.data, 32);
offset += 32;
// r
- memmove(&this->buffer_send[offset], r.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)r.data, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
@@ -1225,6 +1305,7 @@ namespace hw {
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);
+ MDEBUG("FAIL is normal if random is not fixed in proof");
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);
@@ -1233,8 +1314,10 @@ namespace hw {
bool device_ledger::open_tx(crypto::secret_key &tx_key) {
AUTO_LOCK_CMD();
-
+ this->lock();
key_map.clear();
+ hmac_map.clear();
+ this->tx_in_progress = true;
int offset = set_command_header_noopt(INS_OPEN_TX, 0x01);
//account
@@ -1248,7 +1331,13 @@ namespace hw {
this->length_send = offset;
this->exchange();
- memmove(tx_key.data, &this->buffer_recv[32], 32);
+ //skip R, receive: r, r_hmac, fake_a, a_hmac, fake_b, hmac_b
+ unsigned char tmp[32];
+ offset = 32;
+ this->receive_secret((unsigned char*)tx_key.data, offset);
+ this->receive_secret(tmp, offset);
+ this->receive_secret(tmp, offset);
+
#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);
@@ -1276,8 +1365,7 @@ namespace hw {
memmove(&this->buffer_send[offset], public_key.data, 32);
offset += 32;
//sec
- memmove(&this->buffer_send[offset], secret_key.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)secret_key.data, offset);
//id
memmove(&this->buffer_send[offset], payment_id.data, 8);
offset += 8;
@@ -1365,8 +1453,7 @@ namespace hw {
this->buffer_send[offset+3] = tx_version>>0;
offset += 4;
//tx_key
- memmove(&this->buffer_send[offset], tx_key.data, 32);
- offset += 32;
+ this->send_secret((unsigned char*)tx_key.data, offset);
//txkey_pub
memmove(&this->buffer_send[offset], txkey_pub.data, 32);
offset += 32;
@@ -1394,11 +1481,11 @@ namespace hw {
offset++;
//additional_tx_key
if (need_additional_txkeys) {
- memmove(&this->buffer_send[offset], additional_txkey.sec.data, 32);
+ this->send_secret((unsigned char*)additional_txkey.sec.data, offset);
} else {
memset(&this->buffer_send[offset], 0, 32);
+ offset += 32;
}
- offset += 32;
this->buffer_send[4] = offset-5;
this->length_send = offset;
@@ -1411,9 +1498,8 @@ namespace hw {
{
ASSERT_X(recv_len>=32, "Not enought data from device");
crypto::secret_key scalar1;
- memmove(scalar1.data, &this->buffer_recv[offset],32);
+ this->receive_secret((unsigned char*)scalar1.data, offset);
amount_keys.push_back(rct::sk2rct(scalar1));
- offset += 32;
recv_len -= 32;
}
ASSERT_X(recv_len>=32, "Not enought data from device");
@@ -1464,8 +1550,7 @@ namespace hw {
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->send_secret(AKout.bytes, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
@@ -1494,8 +1579,7 @@ namespace hw {
this->buffer_send[offset] = short_amount?0x02:0x00;
offset += 1;
// AKout
- memmove(this->buffer_send+offset, AKout.bytes, 32);
- offset += 32;
+ this->send_secret(AKout.bytes, offset);
//mask k
memmove(this->buffer_send+offset, unmasked.mask.bytes, 32);
offset += 32;
@@ -1535,8 +1619,7 @@ namespace hw {
this->buffer_send[offset] = short_amount?0x02:0x00;
offset += 1;
// AKout
- memmove(this->buffer_send+offset, AKout.bytes, 32);
- offset += 32;
+ this->send_secret(AKout.bytes, offset);
//mask k
memmove(this->buffer_send+offset, masked.mask.bytes, 32);
offset += 32;
@@ -1649,26 +1732,21 @@ namespace hw {
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;
- //Bout
- memmove(this->buffer_send+offset, outKeys.Bout.bytes, 32);
- offset+=32;
- //AKout
- memmove(this->buffer_send+offset, outKeys.AKout.bytes, 32);
- offset+=32;
- } else {
- // dummy: is_subaddress Aout Bout AKout
- offset += 2+32*3;
- }
+ //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;
+ //Bout
+ memmove(this->buffer_send+offset, outKeys.Bout.bytes, 32);
+ offset+=32;
+ //AKout
+ this->send_secret(outKeys.AKout.bytes, offset);
+
//C
memmove(this->buffer_send+offset, data+C_offset,32);
offset += 32;
@@ -1760,17 +1838,19 @@ namespace hw {
memmove(this->buffer_send+offset, H.bytes, 32);
offset += 32;
//mask xin
- memmove(this->buffer_send+offset, xx.bytes, 32);
- offset += 32;
+ this->send_secret(xx.bytes, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
this->exchange();
- memmove(a.bytes, &this->buffer_recv[32*0], 32);
- memmove(aG.bytes, &this->buffer_recv[32*1], 32);
- memmove(aHP.bytes, &this->buffer_recv[32*2], 32);
- memmove(II.bytes, &this->buffer_recv[32*3], 32);
+ offset = 0;
+ this->receive_secret(a.bytes, offset);
+ memmove(aG.bytes, &this->buffer_recv[offset], 32);
+ offset +=32;
+ memmove(aHP.bytes, &this->buffer_recv[offset], 32);
+ offset +=32;
+ memmove(II.bytes, &this->buffer_recv[offset], 32);
#ifdef DEBUG_HWDEVICE
a_x = hw::ledger::decrypt(a);
@@ -1788,6 +1868,7 @@ namespace hw {
bool device_ledger::mlsag_prepare(rct::key &a, rct::key &aG) {
AUTO_LOCK_CMD();
+ int offset;
#ifdef DEBUG_HWDEVICE
rct::key a_x;
@@ -1796,8 +1877,9 @@ namespace hw {
send_simple(INS_MLSAG, 0x01);
- memmove(a.bytes, &this->buffer_recv[32*0], 32);
- memmove(aG.bytes, &this->buffer_recv[32*1], 32);
+ offset = 0;
+ this->receive_secret(a.bytes, offset);
+ memmove(aG.bytes, &this->buffer_recv[offset], 32);
#ifdef DEBUG_HWDEVICE
a_x = hw::ledger::decrypt(a);
@@ -1870,11 +1952,9 @@ namespace hw {
}
offset += 1;
//xx
- memmove(this->buffer_send+offset, xx[j].bytes, 32);
- offset += 32;
+ this->send_secret(xx[j].bytes, offset);
//alpa
- memmove(this->buffer_send+offset, alpha[j].bytes, 32);
- offset += 32;
+ this->send_secret(alpha[j].bytes, offset);
this->buffer_send[4] = offset-5;
this->length_send = offset;
@@ -1900,6 +1980,10 @@ namespace hw {
bool device_ledger::close_tx() {
AUTO_LOCK_CMD();
send_simple(INS_CLOSE_TX);
+ key_map.clear();
+ hmac_map.clear();
+ this->tx_in_progress = false;
+ this->unlock();
return true;
}