mirror of
https://github.com/monero-project/monero.git
synced 2024-11-17 16:27:39 +00:00
device: proper handling of user input
(1) If the user denies something on the Ledger, a proper error message is now shown. (2) Ledger doesn't time out anymore while waiting on user input. (3) Lower the timeout to 2 seconds, this is enough for normal Ledger <-> System communication.
This commit is contained in:
parent
094b0c4d00
commit
6c060e6aaa
5 changed files with 43 additions and 9 deletions
|
@ -50,7 +50,7 @@ namespace hw {
|
||||||
virtual void disconnect() = 0;
|
virtual void disconnect() = 0;
|
||||||
virtual bool connected() const = 0;
|
virtual bool connected() const = 0;
|
||||||
|
|
||||||
virtual int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len) = 0;
|
virtual int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) = 0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -148,7 +148,7 @@ namespace hw {
|
||||||
return this->usb_device != NULL;
|
return this->usb_device != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_io_hid::exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len) {
|
int device_io_hid::exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) {
|
||||||
unsigned char buffer[400];
|
unsigned char buffer[400];
|
||||||
unsigned char padding_buffer[MAX_BLOCK+1];
|
unsigned char padding_buffer[MAX_BLOCK+1];
|
||||||
unsigned int result;
|
unsigned int result;
|
||||||
|
@ -177,7 +177,11 @@ namespace hw {
|
||||||
|
|
||||||
//get first response
|
//get first response
|
||||||
memset(buffer, 0, sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
hid_ret = hid_read_timeout(this->usb_device, buffer, MAX_BLOCK, this->timeout);
|
if (!user_input) {
|
||||||
|
hid_ret = hid_read_timeout(this->usb_device, buffer, MAX_BLOCK, this->timeout);
|
||||||
|
} else {
|
||||||
|
hid_ret = hid_read(this->usb_device, buffer, MAX_BLOCK);
|
||||||
|
}
|
||||||
ASSERT_X(hid_ret>=0, "Unable to read hidapi response. Error "+std::to_string(result)+": "+ safe_hid_error(this->usb_device));
|
ASSERT_X(hid_ret>=0, "Unable to read hidapi response. Error "+std::to_string(result)+": "+ safe_hid_error(this->usb_device));
|
||||||
result = (unsigned int)hid_ret;
|
result = (unsigned int)hid_ret;
|
||||||
io_hid_log(1, buffer, result);
|
io_hid_log(1, buffer, result);
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace hw {
|
||||||
void connect(void *params);
|
void connect(void *params);
|
||||||
void connect(unsigned int vid, unsigned int pid, boost::optional<int> interface_number, boost::optional<unsigned short> usage_page);
|
void connect(unsigned int vid, unsigned int pid, boost::optional<int> interface_number, boost::optional<unsigned short> usage_page);
|
||||||
bool connected() const;
|
bool connected() const;
|
||||||
int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len);
|
int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input);
|
||||||
void disconnect();
|
void disconnect();
|
||||||
void release();
|
void release();
|
||||||
};
|
};
|
||||||
|
|
|
@ -176,7 +176,7 @@ namespace hw {
|
||||||
#define INS_GET_RESPONSE 0xc0
|
#define INS_GET_RESPONSE 0xc0
|
||||||
|
|
||||||
|
|
||||||
device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 120000) {
|
device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 2000) {
|
||||||
this->id = device_id++;
|
this->id = device_id++;
|
||||||
this->reset_buffer();
|
this->reset_buffer();
|
||||||
this->mode = NONE;
|
this->mode = NONE;
|
||||||
|
@ -235,6 +235,9 @@ namespace hw {
|
||||||
/* IO */
|
/* IO */
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
|
|
||||||
|
#define IO_SW_DENY 0x6982
|
||||||
|
#define IO_SECRET_KEY 0x02
|
||||||
|
|
||||||
void device_ledger::logCMD() {
|
void device_ledger::logCMD() {
|
||||||
if (apdu_verbose) {
|
if (apdu_verbose) {
|
||||||
char strbuffer[1024];
|
char strbuffer[1024];
|
||||||
|
@ -283,7 +286,12 @@ namespace hw {
|
||||||
|
|
||||||
void device_ledger::send_simple(unsigned char ins, unsigned char p1) {
|
void device_ledger::send_simple(unsigned char ins, unsigned char p1) {
|
||||||
this->length_send = set_command_header_noopt(ins, p1);
|
this->length_send = set_command_header_noopt(ins, p1);
|
||||||
this->exchange();
|
if (ins == INS_GET_KEY && p1 == IO_SECRET_KEY) {
|
||||||
|
// export view key user input
|
||||||
|
this->exchange_wait_on_input();
|
||||||
|
} else {
|
||||||
|
this->exchange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool device_ledger::reset() {
|
bool device_ledger::reset() {
|
||||||
|
@ -294,7 +302,7 @@ namespace hw {
|
||||||
unsigned int device_ledger::exchange(unsigned int ok, unsigned int mask) {
|
unsigned int device_ledger::exchange(unsigned int ok, unsigned int mask) {
|
||||||
logCMD();
|
logCMD();
|
||||||
|
|
||||||
this->length_recv = hw_device.exchange(this->buffer_send, this->length_send, this->buffer_recv, BUFFER_SEND_SIZE);
|
this->length_recv = hw_device.exchange(this->buffer_send, this->length_send, this->buffer_recv, BUFFER_SEND_SIZE, false);
|
||||||
ASSERT_X(this->length_recv>=2, "Communication error, less than tow bytes received");
|
ASSERT_X(this->length_recv>=2, "Communication error, less than tow bytes received");
|
||||||
|
|
||||||
this->length_recv -= 2;
|
this->length_recv -= 2;
|
||||||
|
@ -305,6 +313,25 @@ namespace hw {
|
||||||
return this->sw;
|
return this->sw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int mask) {
|
||||||
|
logCMD();
|
||||||
|
unsigned int deny = 0;
|
||||||
|
this->length_recv = hw_device.exchange(this->buffer_send, this->length_send, this->buffer_recv, BUFFER_SEND_SIZE, true);
|
||||||
|
ASSERT_X(this->length_recv>=2, "Communication error, less than two bytes received");
|
||||||
|
|
||||||
|
this->length_recv -= 2;
|
||||||
|
this->sw = (this->buffer_recv[length_recv]<<8) | this->buffer_recv[length_recv+1];
|
||||||
|
if (this->sw == IO_SW_DENY) {
|
||||||
|
// cancel on device
|
||||||
|
deny = 1;
|
||||||
|
} else {
|
||||||
|
ASSERT_SW(this->sw,ok,msk);
|
||||||
|
}
|
||||||
|
|
||||||
|
logRESP();
|
||||||
|
return deny;
|
||||||
|
}
|
||||||
|
|
||||||
void device_ledger::reset_buffer() {
|
void device_ledger::reset_buffer() {
|
||||||
this->length_send = 0;
|
this->length_send = 0;
|
||||||
memset(this->buffer_send, 0, BUFFER_SEND_SIZE);
|
memset(this->buffer_send, 0, BUFFER_SEND_SIZE);
|
||||||
|
@ -1260,7 +1287,8 @@ namespace hw {
|
||||||
|
|
||||||
this->buffer_send[4] = offset-5;
|
this->buffer_send[4] = offset-5;
|
||||||
this->length_send = offset;
|
this->length_send = offset;
|
||||||
this->exchange();
|
// check fee user input
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(this->exchange_wait_on_input() == 0, "Fee denied on device.");
|
||||||
|
|
||||||
//pseudoOuts
|
//pseudoOuts
|
||||||
if (type == rct::RCTTypeSimple) {
|
if (type == rct::RCTTypeSimple) {
|
||||||
|
@ -1328,7 +1356,8 @@ namespace hw {
|
||||||
|
|
||||||
this->buffer_send[4] = offset-5;
|
this->buffer_send[4] = offset-5;
|
||||||
this->length_send = offset;
|
this->length_send = offset;
|
||||||
this->exchange();
|
// check transaction user input
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(this->exchange_wait_on_input() == 0, "Transaction denied on device.");
|
||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
hw::ledger::log_hexbuffer("Prehash AKV input", (char*)&this->buffer_recv[64], 3*32);
|
hw::ledger::log_hexbuffer("Prehash AKV input", (char*)&this->buffer_recv[64], 3*32);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -95,6 +95,7 @@ namespace hw {
|
||||||
void logCMD(void);
|
void logCMD(void);
|
||||||
void logRESP(void);
|
void logRESP(void);
|
||||||
unsigned int exchange(unsigned int ok=0x9000, unsigned int mask=0xFFFF);
|
unsigned int exchange(unsigned int ok=0x9000, unsigned int mask=0xFFFF);
|
||||||
|
unsigned int exchange_wait_on_input(unsigned int ok=0x9000, unsigned int mask=0xFFFF);
|
||||||
void reset_buffer(void);
|
void reset_buffer(void);
|
||||||
int set_command_header(unsigned char ins, unsigned char p1 = 0x00, unsigned char p2 = 0x00);
|
int set_command_header(unsigned char ins, unsigned char p1 = 0x00, unsigned char p2 = 0x00);
|
||||||
int set_command_header_noopt(unsigned char ins, unsigned char p1 = 0x00, unsigned char p2 = 0x00);
|
int set_command_header_noopt(unsigned char ins, unsigned char p1 = 0x00, unsigned char p2 = 0x00);
|
||||||
|
|
Loading…
Reference in a new issue