Merge branch 'master' into support_eip1559
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
#include "feature_getEth2PublicKey.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
unsigned int io_seproxyhal_touch_eth2_address_ok(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_eth2_address_ok(__attribute__((unused)) const bagl_element_t *e) {
|
||||
uint32_t tx = set_result_get_eth2_publicKey();
|
||||
G_io_apdu_buffer[tx++] = 0x90;
|
||||
G_io_apdu_buffer[tx++] = 0x00;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "feature_getPublicKey.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
unsigned int io_seproxyhal_touch_address_ok(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_address_ok(__attribute__((unused)) const bagl_element_t *e) {
|
||||
uint32_t tx = set_result_get_publicKey();
|
||||
G_io_apdu_buffer[tx++] = 0x90;
|
||||
G_io_apdu_buffer[tx++] = 0x00;
|
||||
@@ -14,7 +14,7 @@ unsigned int io_seproxyhal_touch_address_ok(const bagl_element_t *e) {
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_address_cancel(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_address_cancel(__attribute__((unused)) const bagl_element_t *e) {
|
||||
G_io_apdu_buffer[0] = 0x69;
|
||||
G_io_apdu_buffer[1] = 0x85;
|
||||
reset_app_context();
|
||||
|
||||
@@ -88,8 +88,10 @@ void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
32,
|
||||
workBuffer + offset,
|
||||
dataLength)) {
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
#endif
|
||||
}
|
||||
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentTokenIndex] = 1;
|
||||
THROW(0x9000);
|
||||
@@ -102,7 +104,7 @@ void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
uint8_t *workBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
__attribute__((unused)) unsigned int *tx) {
|
||||
UNUSED(p1);
|
||||
UNUSED(p2);
|
||||
UNUSED(flags);
|
||||
@@ -143,8 +145,8 @@ void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
chainId = U4BE(workBuffer, offset);
|
||||
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
|
||||
PRINTF("ChainId token mismatch\n");
|
||||
if ((chainConfig->chainId != ETHEREUM_MAINNET_CHAINID) && (chainConfig->chainId != chainId)) {
|
||||
PRINTF("ChainId token mismatch: %d vs %d\n", chainConfig->chainId, chainId);
|
||||
THROW(0x6A80);
|
||||
}
|
||||
offset += 4;
|
||||
@@ -175,8 +177,10 @@ void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
32,
|
||||
workBuffer + offset,
|
||||
dataLength)) {
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,8 +197,10 @@ void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
32,
|
||||
workBuffer + offset,
|
||||
dataLength)) {
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ void handleSetEth2WithdrawalIndex(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
__attribute__((unused)) unsigned int *flags,
|
||||
__attribute__((unused)) unsigned int *tx) {
|
||||
if (dataLength != 4) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
#include "ui_flow.h"
|
||||
#include "tokens.h"
|
||||
|
||||
#define CONTRACT_ADDR_SIZE 20
|
||||
#define SELECTOR_SIZE 4
|
||||
#define SELECTOR_SIZE 4
|
||||
|
||||
void handleSetExternalPlugin(uint8_t p1,
|
||||
uint8_t p2,
|
||||
@@ -19,7 +18,7 @@ void handleSetExternalPlugin(uint8_t p1,
|
||||
uint8_t hash[32];
|
||||
cx_ecfp_public_key_t tokenKey;
|
||||
uint8_t pluginNameLength = *workBuffer;
|
||||
const size_t payload_size = 1 + pluginNameLength + CONTRACT_ADDR_SIZE + SELECTOR_SIZE;
|
||||
const size_t payload_size = 1 + pluginNameLength + ADDRESS_LENGTH + SELECTOR_SIZE;
|
||||
|
||||
if (dataLength <= payload_size) {
|
||||
THROW(0x6A80);
|
||||
@@ -43,7 +42,9 @@ void handleSetExternalPlugin(uint8_t p1,
|
||||
workBuffer + payload_size,
|
||||
dataLength - payload_size)) {
|
||||
PRINTF("Invalid external plugin signature %.*H\n", payload_size, workBuffer);
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
THROW(0x6A80);
|
||||
#endif
|
||||
}
|
||||
|
||||
// move on to the rest of the payload parsing
|
||||
@@ -65,8 +66,8 @@ void handleSetExternalPlugin(uint8_t p1,
|
||||
CATCH_OTHER(e) {
|
||||
PRINTF("%s external plugin is not present\n", dataContext.tokenContext.pluginName);
|
||||
memset(dataContext.tokenContext.pluginName,
|
||||
sizeof(dataContext.tokenContext.pluginName),
|
||||
0);
|
||||
0,
|
||||
sizeof(dataContext.tokenContext.pluginName));
|
||||
THROW(0x6984);
|
||||
}
|
||||
FINALLY {
|
||||
@@ -76,8 +77,8 @@ void handleSetExternalPlugin(uint8_t p1,
|
||||
|
||||
PRINTF("Plugin found\n");
|
||||
|
||||
memmove(dataContext.tokenContext.contract_address, workBuffer, CONTRACT_ADDR_SIZE);
|
||||
workBuffer += 20;
|
||||
memmove(dataContext.tokenContext.contract_address, workBuffer, ADDRESS_LENGTH);
|
||||
workBuffer += ADDRESS_LENGTH;
|
||||
memmove(dataContext.tokenContext.method_selector, workBuffer, SELECTOR_SIZE);
|
||||
externalPluginIsSet = true;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "utils.h"
|
||||
#include "ui_flow.h"
|
||||
|
||||
static const char const SIGN_MAGIC[] =
|
||||
static const char SIGN_MAGIC[] =
|
||||
"\x19"
|
||||
"Ethereum Signed Message:\n";
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#include "shared_context.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_signMessage_ok(__attribute__((unused)) const bagl_element_t *e) {
|
||||
uint8_t privateKeyData[INT256_LENGTH];
|
||||
uint8_t signature[100];
|
||||
uint8_t signatureLength;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint32_t tx = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
@@ -18,14 +17,14 @@ unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) {
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
unsigned int info = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
signatureLength = cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
tmpCtx.messageSigningContext.hash,
|
||||
sizeof(tmpCtx.messageSigningContext.hash),
|
||||
signature,
|
||||
sizeof(signature),
|
||||
&info);
|
||||
cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
tmpCtx.messageSigningContext.hash,
|
||||
sizeof(tmpCtx.messageSigningContext.hash),
|
||||
signature,
|
||||
sizeof(signature),
|
||||
&info);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
G_io_apdu_buffer[0] = 27;
|
||||
if (info & CX_ECCINFO_PARITY_ODD) {
|
||||
@@ -46,7 +45,8 @@ unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) {
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_signMessage_cancel(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_signMessage_cancel(__attribute__((unused))
|
||||
const bagl_element_t *e) {
|
||||
reset_app_context();
|
||||
G_io_apdu_buffer[0] = 0x69;
|
||||
G_io_apdu_buffer[1] = 0x85;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#include "shared_context.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
static const uint8_t const EIP_712_MAGIC[] = {0x19, 0x01};
|
||||
static const uint8_t EIP_712_MAGIC[] = {0x19, 0x01};
|
||||
|
||||
unsigned int io_seproxyhal_touch_signMessage712_v0_ok(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_signMessage712_v0_ok(__attribute__((unused))
|
||||
const bagl_element_t *e) {
|
||||
uint8_t privateKeyData[INT256_LENGTH];
|
||||
uint8_t hash[INT256_LENGTH];
|
||||
uint8_t signature[100];
|
||||
uint8_t signatureLength;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint32_t tx = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
@@ -42,14 +42,14 @@ unsigned int io_seproxyhal_touch_signMessage712_v0_ok(const bagl_element_t *e) {
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
unsigned int info = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
signatureLength = cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
hash,
|
||||
sizeof(hash),
|
||||
signature,
|
||||
sizeof(signature),
|
||||
&info);
|
||||
cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
hash,
|
||||
sizeof(hash),
|
||||
signature,
|
||||
sizeof(signature),
|
||||
&info);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
G_io_apdu_buffer[0] = 27;
|
||||
if (info & CX_ECCINFO_PARITY_ODD) {
|
||||
@@ -70,7 +70,8 @@ unsigned int io_seproxyhal_touch_signMessage712_v0_ok(const bagl_element_t *e) {
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_signMessage712_v0_cancel(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_signMessage712_v0_cancel(__attribute__((unused))
|
||||
const bagl_element_t *e) {
|
||||
reset_app_context();
|
||||
G_io_apdu_buffer[0] = 0x69;
|
||||
G_io_apdu_buffer[1] = 0x85;
|
||||
|
||||
@@ -10,5 +10,5 @@ typedef enum {
|
||||
customStatus_e customProcessor(txContext_t *context);
|
||||
void finalizeParsing(bool direct);
|
||||
void prepareFeeDisplay();
|
||||
void prepareChainIdDisplay();
|
||||
void prepareNetworkDisplay();
|
||||
void ux_approve_tx(bool fromPlugin);
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
#include "utils.h"
|
||||
#include "ui_callbacks.h"
|
||||
#include "ui_flow.h"
|
||||
#include "feature_signTx.h"
|
||||
#ifdef HAVE_STARKWARE
|
||||
#include "stark_utils.h"
|
||||
#endif
|
||||
#include "eth_plugin_handler.h"
|
||||
#include "network.h"
|
||||
|
||||
#define ERR_SILENT_MODE_CHECK_FAILED 0x6001
|
||||
|
||||
@@ -170,7 +172,7 @@ void to_uppercase(char *str, unsigned char size) {
|
||||
}
|
||||
}
|
||||
|
||||
void compareOrCopy(char *preapproved_string, char *parsed_string, bool silent_mode) {
|
||||
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 */
|
||||
@@ -180,7 +182,7 @@ void compareOrCopy(char *preapproved_string, char *parsed_string, bool silent_mo
|
||||
THROW(ERR_SILENT_MODE_CHECK_FAILED);
|
||||
}
|
||||
} else {
|
||||
strcpy(preapproved_string, parsed_string);
|
||||
strlcpy(preapproved_string, parsed_string, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +210,7 @@ static void computeFees(txInt256_t *BEgasPrice, txInt256_t *BEgasLimit, uint256_
|
||||
}
|
||||
|
||||
static void feesToString(uint256_t *rawFee, char *displayBuffer, uint32_t displayBufferSize) {
|
||||
uint8_t *feeTicker = (uint8_t *) PIC(chainConfig->coinName);
|
||||
char *feeTicker = get_network_ticker();
|
||||
uint8_t tickerOffset = 0;
|
||||
uint32_t i;
|
||||
|
||||
@@ -271,38 +273,58 @@ uint32_t get_chainID() {
|
||||
return chain_id;
|
||||
}
|
||||
|
||||
void prepareChainIdDisplay() {
|
||||
uint32_t chainID = get_chainID();
|
||||
uint8_t res = snprintf(strings.common.chainID, sizeof(strings.common.chainID), "%d", chainID);
|
||||
if (res >= sizeof(strings.common.chainID)) {
|
||||
// If the return value is higher or equal to the size passed in as parameter, then
|
||||
// the output was truncated. Return the appropriate error code.
|
||||
THROW(0x6502);
|
||||
void prepareNetworkDisplay() {
|
||||
char *name = get_network_name();
|
||||
if (name == NULL) {
|
||||
// No network name found so simply copy the chain ID as the network name.
|
||||
uint32_t chain_id = get_chain_id();
|
||||
uint8_t res = snprintf(strings.common.network_name,
|
||||
sizeof(strings.common.network_name),
|
||||
"%d",
|
||||
chain_id);
|
||||
if (res >= sizeof(strings.common.network_name)) {
|
||||
// If the return value is higher or equal to the size passed in as parameter, then
|
||||
// the output was truncated. Return the appropriate error code.
|
||||
THROW(0x6502);
|
||||
}
|
||||
} else {
|
||||
// Network name found, simply copy it.
|
||||
strlcpy(strings.common.network_name, name, sizeof(strings.common.network_name));
|
||||
}
|
||||
}
|
||||
|
||||
static void get_public_key(uint8_t *out, uint8_t outLength) {
|
||||
uint8_t privateKeyData[INT256_LENGTH] = {0};
|
||||
cx_ecfp_private_key_t privateKey = {0};
|
||||
cx_ecfp_public_key_t publicKey = {0};
|
||||
|
||||
if (outLength < ADDRESS_LENGTH) {
|
||||
return;
|
||||
}
|
||||
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1,
|
||||
tmpCtx.transactionContext.bip32Path,
|
||||
tmpCtx.transactionContext.pathLength,
|
||||
privateKeyData,
|
||||
NULL);
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
|
||||
cx_ecfp_generate_pair(CX_CURVE_256K1, &publicKey, &privateKey, 1);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
getEthAddressFromKey(&publicKey, out, &global_sha3);
|
||||
}
|
||||
|
||||
void finalizeParsing(bool direct) {
|
||||
char displayBuffer[50];
|
||||
uint8_t decimals = WEI_TO_ETHER;
|
||||
uint8_t *ticker = (uint8_t *) PIC(chainConfig->coinName);
|
||||
char *ticker = get_network_ticker();
|
||||
ethPluginFinalize_t pluginFinalize;
|
||||
tokenDefinition_t *token1 = NULL, *token2 = NULL;
|
||||
bool genericUI = true;
|
||||
|
||||
// Verify the chain
|
||||
if (chainConfig->chainId != 0) {
|
||||
uint32_t id = 0;
|
||||
|
||||
if (txContext.txType == LEGACY) {
|
||||
id = u32_from_BE(txContext.content->v, txContext.content->vLength, true);
|
||||
} else if (txContext.txType == EIP2930 || txContext.txType == EIP1559) {
|
||||
id = u32_from_BE(txContext.content->chainID.value,
|
||||
txContext.content->chainID.length,
|
||||
false);
|
||||
} else {
|
||||
PRINTF("TxType `%u` not supported while checking for chainID\n", txContext.txType);
|
||||
return;
|
||||
}
|
||||
if (chainConfig->chainId != ETHEREUM_MAINNET_CHAINID) {
|
||||
// TODO: Could we remove above check?
|
||||
uint32_t id = get_chain_id();
|
||||
|
||||
if (chainConfig->chainId != id) {
|
||||
PRINTF("Invalid chainID %u expected %u\n", id, chainConfig->chainId);
|
||||
@@ -325,6 +347,11 @@ void finalizeParsing(bool direct) {
|
||||
if (dataContext.tokenContext.pluginStatus >= ETH_PLUGIN_RESULT_SUCCESSFUL) {
|
||||
genericUI = false;
|
||||
eth_plugin_prepare_finalize(&pluginFinalize);
|
||||
|
||||
uint8_t msg_sender[ADDRESS_LENGTH] = {0};
|
||||
get_public_key(msg_sender, sizeof(msg_sender));
|
||||
pluginFinalize.address = msg_sender;
|
||||
|
||||
if (!eth_plugin_call(ETH_PLUGIN_FINALIZE, (void *) &pluginFinalize)) {
|
||||
PRINTF("Plugin finalize call failed\n");
|
||||
reportFinalizeError(direct);
|
||||
@@ -334,22 +361,22 @@ void finalizeParsing(bool direct) {
|
||||
}
|
||||
// Lookup tokens if requested
|
||||
ethPluginProvideToken_t pluginProvideToken;
|
||||
eth_plugin_prepare_provide_token(&pluginProvideToken);
|
||||
if ((pluginFinalize.tokenLookup1 != NULL) || (pluginFinalize.tokenLookup2 != NULL)) {
|
||||
if (pluginFinalize.tokenLookup1 != NULL) {
|
||||
PRINTF("Lookup1: %.*H\n", ADDRESS_LENGTH, pluginFinalize.tokenLookup1);
|
||||
token1 = getKnownToken(pluginFinalize.tokenLookup1);
|
||||
if (token1 != NULL) {
|
||||
PRINTF("Token1 ticker: %s\n", token1->ticker);
|
||||
pluginProvideToken.token1 = getKnownToken(pluginFinalize.tokenLookup1);
|
||||
if (pluginProvideToken.token1 != NULL) {
|
||||
PRINTF("Token1 ticker: %s\n", pluginProvideToken.token1->ticker);
|
||||
}
|
||||
}
|
||||
if (pluginFinalize.tokenLookup2 != NULL) {
|
||||
PRINTF("Lookup2: %.*H\n", ADDRESS_LENGTH, pluginFinalize.tokenLookup2);
|
||||
token2 = getKnownToken(pluginFinalize.tokenLookup2);
|
||||
if (token2 != NULL) {
|
||||
PRINTF("Token2 ticker: %s\n", token2->ticker);
|
||||
pluginProvideToken.token2 = getKnownToken(pluginFinalize.tokenLookup2);
|
||||
if (pluginProvideToken.token2 != NULL) {
|
||||
PRINTF("Token2 ticker: %s\n", pluginProvideToken.token2->ticker);
|
||||
}
|
||||
}
|
||||
eth_plugin_prepare_provide_token(&pluginProvideToken, token1, token2);
|
||||
if (eth_plugin_call(ETH_PLUGIN_PROVIDE_TOKEN, (void *) &pluginProvideToken) <=
|
||||
ETH_PLUGIN_RESULT_UNSUCCESSFUL) {
|
||||
PRINTF("Plugin provide token call failed\n");
|
||||
@@ -384,9 +411,9 @@ void finalizeParsing(bool direct) {
|
||||
tmpContent.txContent.value.length = 32;
|
||||
memmove(tmpContent.txContent.destination, pluginFinalize.address, 20);
|
||||
tmpContent.txContent.destinationLength = 20;
|
||||
if (token1 != NULL) {
|
||||
decimals = token1->decimals;
|
||||
ticker = token1->ticker;
|
||||
if (pluginProvideToken.token1 != NULL) {
|
||||
decimals = pluginProvideToken.token1->decimals;
|
||||
ticker = pluginProvideToken.token1->ticker;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -407,48 +434,50 @@ void finalizeParsing(bool direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare destination address to display
|
||||
if (genericUI) {
|
||||
if (tmpContent.txContent.destinationLength != 0) {
|
||||
displayBuffer[0] = '0';
|
||||
displayBuffer[1] = 'x';
|
||||
getEthAddressStringFromBinary(tmpContent.txContent.destination,
|
||||
(uint8_t *) displayBuffer + 2,
|
||||
displayBuffer + 2,
|
||||
&global_sha3,
|
||||
chainConfig);
|
||||
compareOrCopy(strings.common.fullAddress, displayBuffer, called_from_swap);
|
||||
compareOrCopy(strings.common.fullAddress,
|
||||
sizeof(strings.common.fullAddress),
|
||||
displayBuffer,
|
||||
called_from_swap);
|
||||
} else {
|
||||
strcpy(strings.common.fullAddress, "Contract");
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare amount to display
|
||||
if (genericUI) {
|
||||
amountToString(tmpContent.txContent.value.value,
|
||||
tmpContent.txContent.value.length,
|
||||
decimals,
|
||||
(char *) ticker,
|
||||
ticker,
|
||||
displayBuffer,
|
||||
sizeof(displayBuffer));
|
||||
compareOrCopy(strings.common.fullAmount, displayBuffer, called_from_swap);
|
||||
}
|
||||
// Prepare nonce to display
|
||||
if (genericUI) {
|
||||
uint256_t nonce;
|
||||
convertUint256BE(tmpContent.txContent.nonce.value,
|
||||
tmpContent.txContent.nonce.length,
|
||||
&nonce);
|
||||
tostring256(&nonce, 10, displayBuffer, sizeof(displayBuffer));
|
||||
strncpy(strings.common.nonce, displayBuffer, sizeof(strings.common.nonce));
|
||||
}
|
||||
// Compute maximum fee
|
||||
if (genericUI) {
|
||||
prepareFeeDisplay();
|
||||
compareOrCopy(strings.common.fullAmount,
|
||||
sizeof(strings.common.fullAddress),
|
||||
displayBuffer,
|
||||
called_from_swap);
|
||||
}
|
||||
|
||||
// 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 maximum fee
|
||||
prepareFeeDisplay();
|
||||
|
||||
// Prepare chainID field
|
||||
if (genericUI) {
|
||||
prepareChainIdDisplay();
|
||||
}
|
||||
prepareNetworkDisplay();
|
||||
|
||||
bool no_consent;
|
||||
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
#include "utils.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_tx_ok(__attribute__((unused)) const bagl_element_t *e) {
|
||||
uint8_t privateKeyData[INT256_LENGTH];
|
||||
uint8_t signature[100];
|
||||
uint8_t signatureLength;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint32_t tx = 0;
|
||||
uint32_t v = u32_from_BE(tmpContent.txContent.v, tmpContent.txContent.vLength, true);
|
||||
@@ -19,14 +18,14 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) {
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
unsigned int info = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
signatureLength = cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
tmpCtx.transactionContext.hash,
|
||||
sizeof(tmpCtx.transactionContext.hash),
|
||||
signature,
|
||||
sizeof(signature),
|
||||
&info);
|
||||
cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
tmpCtx.transactionContext.hash,
|
||||
sizeof(tmpCtx.transactionContext.hash),
|
||||
signature,
|
||||
sizeof(signature),
|
||||
&info);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
if (txContext.txType == EIP1559 || txContext.txType == EIP2930) {
|
||||
if (info & CX_ECCINFO_PARITY_ODD) {
|
||||
@@ -66,7 +65,7 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) {
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_tx_cancel(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_tx_cancel(__attribute__((unused)) const bagl_element_t *e) {
|
||||
reset_app_context();
|
||||
G_io_apdu_buffer[0] = 0x69;
|
||||
G_io_apdu_buffer[1] = 0x85;
|
||||
@@ -77,7 +76,7 @@ unsigned int io_seproxyhal_touch_tx_cancel(const bagl_element_t *e) {
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_data_ok(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_data_ok(__attribute__((unused)) const bagl_element_t *e) {
|
||||
parserStatus_e txResult = USTREAM_FINISHED;
|
||||
txResult = continueTx(&txContext);
|
||||
switch (txResult) {
|
||||
@@ -108,7 +107,7 @@ unsigned int io_seproxyhal_touch_data_ok(const bagl_element_t *e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_data_cancel(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_data_cancel(__attribute__((unused)) const bagl_element_t *e) {
|
||||
reset_app_context();
|
||||
io_seproxyhal_send_status(0x6985);
|
||||
// Display back the original UX
|
||||
|
||||
@@ -3,80 +3,9 @@
|
||||
#include "chainConfig.h"
|
||||
#include "utils.h"
|
||||
#include "feature_signTx.h"
|
||||
#include "network.h"
|
||||
#include "eth_plugin_handler.h"
|
||||
|
||||
void plugin_ui_get_id() {
|
||||
ethQueryContractID_t pluginQueryContractID;
|
||||
eth_plugin_prepare_query_contract_ID(&pluginQueryContractID,
|
||||
strings.common.fullAddress,
|
||||
sizeof(strings.common.fullAddress),
|
||||
strings.common.fullAmount,
|
||||
sizeof(strings.common.fullAmount));
|
||||
// Query the original contract for ID if it's not an internal alias
|
||||
if (!eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_ID, (void *) &pluginQueryContractID)) {
|
||||
PRINTF("Plugin query contract ID call failed\n");
|
||||
io_seproxyhal_touch_tx_cancel(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void plugin_ui_get_item() {
|
||||
ethQueryContractUI_t pluginQueryContractUI;
|
||||
eth_plugin_prepare_query_contract_UI(&pluginQueryContractUI,
|
||||
dataContext.tokenContext.pluginUiCurrentItem,
|
||||
strings.common.fullAddress,
|
||||
sizeof(strings.common.fullAddress),
|
||||
strings.common.fullAmount,
|
||||
sizeof(strings.common.fullAmount));
|
||||
if (!eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_UI, (void *) &pluginQueryContractUI)) {
|
||||
PRINTF("Plugin query contract UI call failed\n");
|
||||
io_seproxyhal_touch_tx_cancel(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void display_next_plugin_item(bool entering) {
|
||||
if (entering) {
|
||||
if (dataContext.tokenContext.pluginUiState == PLUGIN_UI_OUTSIDE) {
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_INSIDE;
|
||||
dataContext.tokenContext.pluginUiCurrentItem = 0;
|
||||
plugin_ui_get_item();
|
||||
ux_flow_next();
|
||||
} else {
|
||||
if (dataContext.tokenContext.pluginUiCurrentItem > 0) {
|
||||
dataContext.tokenContext.pluginUiCurrentItem--;
|
||||
plugin_ui_get_item();
|
||||
ux_flow_next();
|
||||
} else {
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE;
|
||||
dataContext.tokenContext.pluginUiCurrentItem = 0;
|
||||
ux_flow_prev();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (dataContext.tokenContext.pluginUiState == PLUGIN_UI_OUTSIDE) {
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_INSIDE;
|
||||
plugin_ui_get_item();
|
||||
ux_flow_prev();
|
||||
} else {
|
||||
if (dataContext.tokenContext.pluginUiCurrentItem <
|
||||
dataContext.tokenContext.pluginUiMaxItems - 1) {
|
||||
dataContext.tokenContext.pluginUiCurrentItem++;
|
||||
plugin_ui_get_item();
|
||||
ux_flow_prev();
|
||||
// Reset multi page layout to the first page
|
||||
G_ux.layout_paging.current = 0;
|
||||
#ifdef TARGET_NANOS
|
||||
ux_layout_paging_redisplay_by_addr(G_ux.stack_count - 1);
|
||||
#else
|
||||
ux_layout_bnnn_paging_redisplay(0);
|
||||
#endif
|
||||
} else {
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE;
|
||||
ux_flow_next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_confirm_selector_flow_1_step,
|
||||
@@ -224,11 +153,11 @@ UX_STEP_NOCB(
|
||||
.text = strings.common.maxFee,
|
||||
});
|
||||
UX_STEP_NOCB(
|
||||
ux_approval_chainid_step,
|
||||
ux_approval_network_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Chain ID",
|
||||
.text = strings.common.chainID,
|
||||
.title = "Network",
|
||||
.text = strings.common.network_name,
|
||||
});
|
||||
|
||||
UX_STEP_CB(
|
||||
@@ -277,15 +206,13 @@ void ux_approve_tx(bool fromPlugin) {
|
||||
}
|
||||
|
||||
if (fromPlugin) {
|
||||
// If we're coming from a plugin then we need to prepare the display.
|
||||
prepareChainIdDisplay();
|
||||
prepareFeeDisplay();
|
||||
|
||||
// Add the special dynamic display logic
|
||||
ux_approval_tx_flow[step++] = &ux_plugin_approval_id_step;
|
||||
ux_approval_tx_flow[step++] = &ux_plugin_approval_before_step;
|
||||
ux_approval_tx_flow[step++] = &ux_plugin_approval_display_step;
|
||||
ux_approval_tx_flow[step++] = &ux_plugin_approval_after_step;
|
||||
} else {
|
||||
// We're in a regular transaction, just show the amount and the address
|
||||
ux_approval_tx_flow[step++] = &ux_approval_amount_step;
|
||||
ux_approval_tx_flow[step++] = &ux_approval_address_step;
|
||||
}
|
||||
@@ -294,19 +221,12 @@ void ux_approve_tx(bool fromPlugin) {
|
||||
ux_approval_tx_flow[step++] = &ux_approval_nonce_step;
|
||||
}
|
||||
|
||||
uint32_t id;
|
||||
if (txContext.txType == LEGACY) {
|
||||
id = u32_from_BE(txContext.content->v, txContext.content->vLength, true);
|
||||
} else if (txContext.txType == EIP2930 || txContext.txType == EIP1559) {
|
||||
id =
|
||||
u32_from_BE(txContext.content->chainID.value, txContext.content->chainID.length, false);
|
||||
} else {
|
||||
PRINTF("TxType `%u` not supported while preparing to approve tx\n", txContext.txType);
|
||||
THROW(0x6501);
|
||||
}
|
||||
if (id != ETHEREUM_MAINNET_CHAINID) {
|
||||
ux_approval_tx_flow[step++] = &ux_approval_chainid_step;
|
||||
uint32_t chain_id = get_chain_id();
|
||||
if (chainConfig->chainId == ETHEREUM_MAINNET_CHAINID && chain_id != chainConfig->chainId) {
|
||||
// TODO: do we need the `&&` above?
|
||||
ux_approval_tx_flow[step++] = &ux_approval_network_step;
|
||||
}
|
||||
|
||||
ux_approval_tx_flow[step++] = &ux_approval_fees_step;
|
||||
ux_approval_tx_flow[step++] = &ux_approval_accept_step;
|
||||
ux_approval_tx_flow[step++] = &ux_approval_reject_step;
|
||||
|
||||
82
src_features/signTx/ui_plugin.c
Normal file
82
src_features/signTx/ui_plugin.c
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "feature_signTx.h"
|
||||
#include "ux.h"
|
||||
#include "eth_plugin_handler.h"
|
||||
#include "ui_callbacks.h"
|
||||
#include "ui_plugin.h"
|
||||
|
||||
#ifdef TARGET_NANOS
|
||||
// This function is not exported by the SDK
|
||||
void ux_layout_paging_redisplay_by_addr(unsigned int stack_slot);
|
||||
#endif
|
||||
|
||||
void plugin_ui_get_id() {
|
||||
ethQueryContractID_t pluginQueryContractID;
|
||||
eth_plugin_prepare_query_contract_ID(&pluginQueryContractID,
|
||||
strings.common.fullAddress,
|
||||
sizeof(strings.common.fullAddress),
|
||||
strings.common.fullAmount,
|
||||
sizeof(strings.common.fullAmount));
|
||||
// Query the original contract for ID if it's not an internal alias
|
||||
if (!eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_ID, (void *) &pluginQueryContractID)) {
|
||||
PRINTF("Plugin query contract ID call failed\n");
|
||||
io_seproxyhal_touch_tx_cancel(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void plugin_ui_get_item() {
|
||||
ethQueryContractUI_t pluginQueryContractUI;
|
||||
eth_plugin_prepare_query_contract_UI(&pluginQueryContractUI,
|
||||
dataContext.tokenContext.pluginUiCurrentItem,
|
||||
strings.common.fullAddress,
|
||||
sizeof(strings.common.fullAddress),
|
||||
strings.common.fullAmount,
|
||||
sizeof(strings.common.fullAmount));
|
||||
if (!eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_UI, (void *) &pluginQueryContractUI)) {
|
||||
PRINTF("Plugin query contract UI call failed\n");
|
||||
io_seproxyhal_touch_tx_cancel(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void display_next_plugin_item(bool entering) {
|
||||
if (entering) {
|
||||
if (dataContext.tokenContext.pluginUiState == PLUGIN_UI_OUTSIDE) {
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_INSIDE;
|
||||
dataContext.tokenContext.pluginUiCurrentItem = 0;
|
||||
plugin_ui_get_item();
|
||||
ux_flow_next();
|
||||
} else {
|
||||
if (dataContext.tokenContext.pluginUiCurrentItem > 0) {
|
||||
dataContext.tokenContext.pluginUiCurrentItem--;
|
||||
plugin_ui_get_item();
|
||||
ux_flow_next();
|
||||
} else {
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE;
|
||||
dataContext.tokenContext.pluginUiCurrentItem = 0;
|
||||
ux_flow_prev();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (dataContext.tokenContext.pluginUiState == PLUGIN_UI_OUTSIDE) {
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_INSIDE;
|
||||
plugin_ui_get_item();
|
||||
ux_flow_prev();
|
||||
} else {
|
||||
if (dataContext.tokenContext.pluginUiCurrentItem <
|
||||
dataContext.tokenContext.pluginUiMaxItems - 1) {
|
||||
dataContext.tokenContext.pluginUiCurrentItem++;
|
||||
plugin_ui_get_item();
|
||||
ux_flow_prev();
|
||||
// Reset multi page layout to the first page
|
||||
G_ux.layout_paging.current = 0;
|
||||
#ifdef TARGET_NANOS
|
||||
ux_layout_paging_redisplay_by_addr(G_ux.stack_count - 1);
|
||||
#else
|
||||
ux_layout_bnnn_paging_redisplay(0);
|
||||
#endif
|
||||
} else {
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE;
|
||||
ux_flow_next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
src_features/signTx/ui_plugin.h
Normal file
5
src_features/signTx/ui_plugin.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
void plugin_ui_get_id();
|
||||
void plugin_ui_get_item();
|
||||
void display_next_plugin_item(bool entering);
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "ui_callbacks.h"
|
||||
#include "feature_stark_getPublicKey.h"
|
||||
|
||||
unsigned int io_seproxyhal_touch_stark_pubkey_ok(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_stark_pubkey_ok(__attribute__((unused)) const bagl_element_t *e) {
|
||||
uint32_t tx = set_result_get_stark_publicKey();
|
||||
G_io_apdu_buffer[tx++] = 0x90;
|
||||
G_io_apdu_buffer[tx++] = 0x00;
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
#include "ui_flow.h"
|
||||
|
||||
void handleStarkwareProvideQuantum(uint8_t p1,
|
||||
uint8_t p2,
|
||||
__attribute__((unused)) uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
__attribute__((unused)) unsigned int *flags,
|
||||
__attribute__((unused)) unsigned int *tx) {
|
||||
size_t i = 0;
|
||||
uint8_t expectedDataSize = 20 + 32;
|
||||
uint8_t addressZero = 0;
|
||||
|
||||
@@ -16,7 +16,7 @@ void handleStarkwareSignMessage(uint8_t p1,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
__attribute__((unused)) unsigned int *tx) {
|
||||
uint8_t privateKeyData[INT256_LENGTH];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = *(dataBuffer);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "stark_utils.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_stark_ok(__attribute__((unused)) const bagl_element_t *e) {
|
||||
uint8_t privateKeyData[32];
|
||||
uint8_t signature[72];
|
||||
uint32_t tx = 0;
|
||||
|
||||
@@ -17,7 +17,7 @@ void stark_sign_display_condition_address() {
|
||||
strings.tmp.tmp[0] = '0';
|
||||
strings.tmp.tmp[1] = 'x';
|
||||
getEthAddressStringFromBinary(dataContext.starkContext.conditionAddress,
|
||||
(uint8_t *) (strings.tmp.tmp + 2),
|
||||
strings.tmp.tmp + 2,
|
||||
&global_sha3,
|
||||
chainConfig);
|
||||
strings.tmp.tmp[42] = '\0';
|
||||
|
||||
@@ -11,7 +11,7 @@ void handleStarkwareUnsafeSign(uint8_t p1,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
__attribute__((unused)) unsigned int *tx) {
|
||||
uint32_t i;
|
||||
uint8_t privateKeyData[INT256_LENGTH];
|
||||
cx_ecfp_public_key_t publicKey;
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
#include "stark_utils.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
unsigned int io_seproxyhal_touch_stark_unsafe_sign_ok(const bagl_element_t *e) {
|
||||
unsigned int io_seproxyhal_touch_stark_unsafe_sign_ok(__attribute__((unused))
|
||||
const bagl_element_t *e) {
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint8_t privateKeyData[INT256_LENGTH];
|
||||
uint8_t signature[72];
|
||||
|
||||
Reference in New Issue
Block a user