Improve finalizeParsing() checking in swap context
Simplify code in logic_signTx.c
This commit is contained in:
@@ -170,26 +170,6 @@ customStatus_e customProcessor(txContext_t *context) {
|
||||
return CUSTOM_NOT_HANDLED;
|
||||
}
|
||||
|
||||
void to_uppercase(char *str, unsigned char size) {
|
||||
for (unsigned char i = 0; i < size && str[i] != 0; i++) {
|
||||
str[i] = str[i] >= 'a' ? str[i] - ('a' - 'A') : str[i];
|
||||
}
|
||||
}
|
||||
|
||||
void compareOrCopy(char *preapproved_string, size_t size, char *parsed_string, bool silent_mode) {
|
||||
if (silent_mode) {
|
||||
/* ETH address are not fundamentally case sensitive but might
|
||||
have some for checksum purpose, so let's get rid of these diffs */
|
||||
to_uppercase(preapproved_string, strlen(preapproved_string));
|
||||
to_uppercase(parsed_string, strlen(parsed_string));
|
||||
if (memcmp(preapproved_string, parsed_string, strlen(preapproved_string))) {
|
||||
THROW(ERR_SILENT_MODE_CHECK_FAILED);
|
||||
}
|
||||
} else {
|
||||
strlcpy(preapproved_string, parsed_string, size);
|
||||
}
|
||||
}
|
||||
|
||||
void reportFinalizeError(bool direct) {
|
||||
reset_app_context();
|
||||
if (direct) {
|
||||
@@ -200,20 +180,20 @@ void reportFinalizeError(bool direct) {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert `BEgasPrice` and `BEgasLimit` to Uint256 and then stores the multiplication of both in
|
||||
// `output`.
|
||||
static void computeFees(txInt256_t *BEgasPrice, txInt256_t *BEgasLimit, uint256_t *output) {
|
||||
uint256_t gasPrice = {0};
|
||||
uint256_t gasLimit = {0};
|
||||
|
||||
PRINTF("Gas price %.*H\n", BEgasPrice->length, BEgasPrice->value);
|
||||
PRINTF("Gas limit %.*H\n", BEgasLimit->length, BEgasLimit->value);
|
||||
convertUint256BE(BEgasPrice->value, BEgasPrice->length, &gasPrice);
|
||||
convertUint256BE(BEgasLimit->value, BEgasLimit->length, &gasLimit);
|
||||
mul256(&gasPrice, &gasLimit, output);
|
||||
static void address_to_string(uint8_t *in,
|
||||
size_t in_len,
|
||||
char *out,
|
||||
size_t out_len,
|
||||
cx_sha3_t *sha3,
|
||||
uint64_t chainId) {
|
||||
if (in_len != 0) {
|
||||
getEthDisplayableAddress(in, out, out_len, sha3, chainId);
|
||||
} else {
|
||||
strlcpy(out, "Contract", out_len);
|
||||
}
|
||||
}
|
||||
|
||||
static void feesToString(uint256_t *rawFee, char *displayBuffer, uint32_t displayBufferSize) {
|
||||
static void raw_fee_to_string(uint256_t *rawFee, char *displayBuffer, uint32_t displayBufferSize) {
|
||||
const char *feeTicker = get_network_ticker();
|
||||
uint8_t tickerOffset = 0;
|
||||
uint32_t i;
|
||||
@@ -255,32 +235,40 @@ static void feesToString(uint256_t *rawFee, char *displayBuffer, uint32_t displa
|
||||
}
|
||||
|
||||
// Compute the fees, transform it to a string, prepend a ticker to it and copy everything to
|
||||
// `displayBuffer`.
|
||||
void prepareAndCopyFees(txInt256_t *BEGasPrice,
|
||||
txInt256_t *BEGasLimit,
|
||||
char *displayBuffer,
|
||||
uint32_t displayBufferSize) {
|
||||
// `displayBuffer` output
|
||||
static void max_transaction_fee_to_string(const txInt256_t *BEGasPrice,
|
||||
const txInt256_t *BEGasLimit,
|
||||
char *displayBuffer,
|
||||
uint32_t displayBufferSize) {
|
||||
// Use temporary variables to convert values to uint256_t
|
||||
uint256_t gasPrice = {0};
|
||||
uint256_t gasLimit = {0};
|
||||
// Use temporary variable to store the result of the operation in uint256_t
|
||||
uint256_t rawFee = {0};
|
||||
computeFees(BEGasPrice, BEGasLimit, &rawFee);
|
||||
feesToString(&rawFee, displayBuffer, displayBufferSize);
|
||||
|
||||
PRINTF("Gas price %.*H\n", BEGasPrice->length, BEGasPrice->value);
|
||||
PRINTF("Gas limit %.*H\n", BEGasLimit->length, BEGasLimit->value);
|
||||
convertUint256BE(BEGasPrice->value, BEGasPrice->length, &gasPrice);
|
||||
convertUint256BE(BEGasLimit->value, BEGasLimit->length, &gasLimit);
|
||||
mul256(&gasPrice, &gasLimit, &rawFee);
|
||||
raw_fee_to_string(&rawFee, displayBuffer, displayBufferSize);
|
||||
}
|
||||
|
||||
void prepareFeeDisplay() {
|
||||
prepareAndCopyFees(&tmpContent.txContent.gasprice,
|
||||
&tmpContent.txContent.startgas,
|
||||
strings.common.maxFee,
|
||||
sizeof(strings.common.maxFee));
|
||||
static void nonce_to_string(const txInt256_t *nonce, char *out, size_t out_size) {
|
||||
uint256_t nonce_uint256;
|
||||
convertUint256BE(nonce->value, nonce->length, &nonce_uint256);
|
||||
tostring256(&nonce_uint256, 10, out, out_size);
|
||||
}
|
||||
|
||||
void prepareNetworkDisplay() {
|
||||
static void get_network_as_string(char *out, size_t out_size) {
|
||||
const char *name = get_network_name();
|
||||
if (name == NULL) {
|
||||
// No network name found so simply copy the chain ID as the network name.
|
||||
uint64_t chain_id = get_chain_id();
|
||||
u64_to_string(chain_id, strings.common.network_name, sizeof(strings.common.network_name));
|
||||
u64_to_string(chain_id, out, out_size);
|
||||
} else {
|
||||
// Network name found, simply copy it.
|
||||
strlcpy(strings.common.network_name, name, sizeof(strings.common.network_name));
|
||||
strlcpy(out, name, out_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,7 +298,7 @@ void finalizeParsing(bool direct) {
|
||||
uint8_t decimals = WEI_TO_ETHER;
|
||||
const char *ticker = get_network_ticker();
|
||||
ethPluginFinalize_t pluginFinalize;
|
||||
bool genericUI = true;
|
||||
bool use_standard_UI = true;
|
||||
|
||||
// Verify the chain
|
||||
if (chainConfig->chainId != ETHEREUM_MAINNET_CHAINID) {
|
||||
@@ -335,7 +323,6 @@ void finalizeParsing(bool direct) {
|
||||
|
||||
// Finalize the plugin handling
|
||||
if (dataContext.tokenContext.pluginStatus >= ETH_PLUGIN_RESULT_SUCCESSFUL) {
|
||||
genericUI = false;
|
||||
eth_plugin_prepare_finalize(&pluginFinalize);
|
||||
|
||||
uint8_t msg_sender[ADDRESS_LENGTH] = {0};
|
||||
@@ -381,6 +368,8 @@ void finalizeParsing(bool direct) {
|
||||
// Handle the right interface
|
||||
switch (pluginFinalize.uiType) {
|
||||
case ETH_UI_TYPE_GENERIC:
|
||||
// Use the dedicated ETH plugin UI
|
||||
use_standard_UI = false;
|
||||
tmpContent.txContent.dataPresent = false;
|
||||
// Add the number of screens + the number of additional screens to get the total
|
||||
// number of screens needed.
|
||||
@@ -388,7 +377,8 @@ void finalizeParsing(bool direct) {
|
||||
pluginFinalize.numScreens + pluginProvideInfo.additionalScreens;
|
||||
break;
|
||||
case ETH_UI_TYPE_AMOUNT_ADDRESS:
|
||||
genericUI = true;
|
||||
// Use the standard ETH UI as this plugin uses the amount/address UI
|
||||
use_standard_UI = true;
|
||||
tmpContent.txContent.dataPresent = false;
|
||||
if ((pluginFinalize.amount == NULL) || (pluginFinalize.address == NULL)) {
|
||||
PRINTF("Incorrect amount/address set by plugin\n");
|
||||
@@ -413,11 +403,14 @@ void finalizeParsing(bool direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
genericUI = true;
|
||||
}
|
||||
}
|
||||
|
||||
// User has just validated a swap but ETH received apdus about a non standard plugin / contract
|
||||
if (called_from_swap && !use_standard_UI) {
|
||||
THROW(ERR_SILENT_MODE_CHECK_FAILED);
|
||||
}
|
||||
|
||||
if (tmpContent.txContent.dataPresent && !N_storage.dataAllowed) {
|
||||
reportFinalizeError(direct);
|
||||
ui_warning_contract_data();
|
||||
@@ -426,66 +419,97 @@ void finalizeParsing(bool direct) {
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare destination address to display
|
||||
if (genericUI) {
|
||||
if (tmpContent.txContent.destinationLength != 0) {
|
||||
getEthDisplayableAddress(tmpContent.txContent.destination,
|
||||
displayBuffer,
|
||||
sizeof(displayBuffer),
|
||||
&global_sha3,
|
||||
chainConfig->chainId);
|
||||
compareOrCopy(strings.common.fullAddress,
|
||||
sizeof(strings.common.fullAddress),
|
||||
// Prepare destination address and amount to display
|
||||
if (use_standard_UI) {
|
||||
// Format the address in a temporary buffer, if in swap case compare it with validated
|
||||
// address, else commit it
|
||||
address_to_string(tmpContent.txContent.destination,
|
||||
tmpContent.txContent.destinationLength,
|
||||
displayBuffer,
|
||||
called_from_swap);
|
||||
sizeof(displayBuffer),
|
||||
&global_sha3,
|
||||
chainConfig->chainId);
|
||||
if (called_from_swap) {
|
||||
// Ensure the values are the same that the ones that have been previously validated
|
||||
if (strncasecmp(strings.common.fullAddress,
|
||||
displayBuffer,
|
||||
MIN(sizeof(strings.common.fullAddress), sizeof(displayBuffer))) != 0) {
|
||||
THROW(ERR_SILENT_MODE_CHECK_FAILED);
|
||||
}
|
||||
} else {
|
||||
strcpy(strings.common.fullAddress, "Contract");
|
||||
strlcpy(strings.common.fullAddress, displayBuffer, sizeof(strings.common.fullAddress));
|
||||
}
|
||||
}
|
||||
PRINTF("Address displayed: %s\n", strings.common.fullAddress);
|
||||
|
||||
// Prepare amount to display
|
||||
if (genericUI) {
|
||||
// Format the amount in a temporary buffer, if in swap case compare it with validated
|
||||
// amount, else commit it
|
||||
amountToString(tmpContent.txContent.value.value,
|
||||
tmpContent.txContent.value.length,
|
||||
decimals,
|
||||
ticker,
|
||||
displayBuffer,
|
||||
sizeof(displayBuffer));
|
||||
compareOrCopy(strings.common.fullAmount,
|
||||
sizeof(strings.common.fullAmount),
|
||||
displayBuffer,
|
||||
called_from_swap);
|
||||
if (called_from_swap) {
|
||||
// Ensure the values are the same that the ones that have been previously validated
|
||||
if (strncmp(strings.common.fullAmount,
|
||||
displayBuffer,
|
||||
MIN(sizeof(strings.common.fullAmount), sizeof(displayBuffer))) != 0) {
|
||||
THROW(ERR_SILENT_MODE_CHECK_FAILED);
|
||||
}
|
||||
} else {
|
||||
strlcpy(strings.common.fullAmount, displayBuffer, sizeof(strings.common.fullAmount));
|
||||
}
|
||||
PRINTF("Amount displayed: %s\n", strings.common.fullAmount);
|
||||
}
|
||||
|
||||
// Prepare nonce to display
|
||||
uint256_t nonce;
|
||||
convertUint256BE(tmpContent.txContent.nonce.value, tmpContent.txContent.nonce.length, &nonce);
|
||||
tostring256(&nonce, 10, displayBuffer, sizeof(displayBuffer));
|
||||
strlcpy(strings.common.nonce, displayBuffer, sizeof(strings.common.nonce));
|
||||
// Compute the max fee in a temporary buffer, if in swap case compare it with validated max fee,
|
||||
// else commit it
|
||||
max_transaction_fee_to_string(&tmpContent.txContent.gasprice,
|
||||
&tmpContent.txContent.startgas,
|
||||
displayBuffer,
|
||||
sizeof(displayBuffer));
|
||||
if (called_from_swap) {
|
||||
// Ensure the values are the same that the ones that have been previously validated
|
||||
if (strncmp(strings.common.maxFee,
|
||||
displayBuffer,
|
||||
MIN(sizeof(strings.common.maxFee), sizeof(displayBuffer))) != 0) {
|
||||
THROW(ERR_SILENT_MODE_CHECK_FAILED);
|
||||
}
|
||||
} else {
|
||||
strlcpy(strings.common.maxFee, displayBuffer, sizeof(strings.common.maxFee));
|
||||
}
|
||||
|
||||
// Compute maximum fee
|
||||
prepareFeeDisplay();
|
||||
PRINTF("Fees displayed: %s\n", strings.common.maxFee);
|
||||
|
||||
// Prepare nonce to display
|
||||
nonce_to_string(&tmpContent.txContent.nonce,
|
||||
strings.common.nonce,
|
||||
sizeof(strings.common.nonce));
|
||||
PRINTF("Nonce: %s\n", strings.common.nonce);
|
||||
|
||||
// Prepare chainID field
|
||||
prepareNetworkDisplay();
|
||||
get_network_as_string(strings.common.network_name, sizeof(strings.common.network_name));
|
||||
PRINTF("Network: %s\n", strings.common.network_name);
|
||||
|
||||
bool no_consent;
|
||||
bool no_consent_check;
|
||||
|
||||
no_consent = called_from_swap;
|
||||
// If called from swap, the user as already validated a standard transaction
|
||||
// We have already checked the fields of this transaction above
|
||||
no_consent_check = called_from_swap && use_standard_UI;
|
||||
|
||||
#ifdef NO_CONSENT
|
||||
no_consent = true;
|
||||
no_consent_check = true;
|
||||
#endif // NO_CONSENT
|
||||
|
||||
if (no_consent) {
|
||||
if (no_consent_check) {
|
||||
io_seproxyhal_touch_tx_ok(NULL);
|
||||
} else {
|
||||
if (genericUI) {
|
||||
if (use_standard_UI) {
|
||||
ux_approve_tx(false);
|
||||
} else {
|
||||
plugin_ui_start();
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE;
|
||||
dataContext.tokenContext.pluginUiCurrentItem = 0;
|
||||
ux_approve_tx(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user