diff --git a/Makefile b/Makefile index 0735f94..7d4c45e 100755 --- a/Makefile +++ b/Makefile @@ -266,6 +266,12 @@ ifneq ($(ALLOW_DATA),0) DEFINES += HAVE_ALLOW_DATA endif +# Bypass the signature verification for setExternalPlugin and provideERC20TokenInfo calls +BYPASS_SIGNATURES:=0 +ifneq ($(BYPASS_SIGNATURES),0) +DEFINES += HAVE_BYPASS_SIGNATURES +endif + # Enabling debug PRINTF DEBUG:=0 diff --git a/doc/ethapp_plugins.asc b/doc/ethapp_plugins.asc index b112639..d142852 100644 --- a/doc/ethapp_plugins.asc +++ b/doc/ethapp_plugins.asc @@ -148,7 +148,7 @@ typedef struct ethPluginFinalize_t { uint8_t *tokenLookup2; uint8_t *amount; // set an uint256 pointer if uiType is UI_AMOUNT_ADDRESS - uint8_t *address; // set to a 20 bytes address pointer if uiType is UI_AMOUNT_ADDRESS + uint8_t *address; // set to the destination address if uiType is UI_AMOUNT_ADDRESS. Set to the user's address if uiType is UI_TYPE_GENERIC uint8_t uiType; uint8_t numScreens; // ignored if uiType is UI_AMOUNT_ADDRESS diff --git a/ethereum-plugin-sdk b/ethereum-plugin-sdk index 75bf9f4..aeaf645 160000 --- a/ethereum-plugin-sdk +++ b/ethereum-plugin-sdk @@ -1 +1 @@ -Subproject commit 75bf9f421ff7c15cfd92c75f2131ffcc622c44b3 +Subproject commit aeaf6450c32c8134a7d19b1852554771ca8bc4be diff --git a/src/eth_plugin_handler.c b/src/eth_plugin_handler.c index 30c5bc0..ed9cbd7 100644 --- a/src/eth_plugin_handler.c +++ b/src/eth_plugin_handler.c @@ -21,12 +21,8 @@ void eth_plugin_prepare_finalize(ethPluginFinalize_t *finalize) { memset((uint8_t *) finalize, 0, sizeof(ethPluginFinalize_t)); } -void eth_plugin_prepare_provide_token(ethPluginProvideToken_t *provideToken, - tokenDefinition_t *token1, - tokenDefinition_t *token2) { +void eth_plugin_prepare_provide_token(ethPluginProvideToken_t *provideToken) { memset((uint8_t *) provideToken, 0, sizeof(ethPluginProvideToken_t)); - provideToken->token1 = token1; - provideToken->token2 = token2; } void eth_plugin_prepare_query_contract_ID(ethQueryContractID_t *queryContractID, @@ -67,11 +63,19 @@ eth_plugin_result_t eth_plugin_perform_init(uint8_t *contractAddress, if (memcmp(contractAddress, dataContext.tokenContext.contract_address, sizeof(dataContext.tokenContext.contract_address)) != 0) { + PRINTF("Got contract: %.*H\n", ADDRESS_LENGTH, contractAddress); + PRINTF("Expected contract: %.*H\n", + ADDRESS_LENGTH, + dataContext.tokenContext.contract_address); os_sched_exit(0); } if (memcmp(init->selector, dataContext.tokenContext.method_selector, sizeof(dataContext.tokenContext.method_selector)) != 0) { + PRINTF("Got selector: %.*H\n", SELECTOR_SIZE, init->selector); + PRINTF("Expected selector: %.*H\n", + SELECTOR_SIZE, + dataContext.tokenContext.method_selector); os_sched_exit(0); } PRINTF("External plugin will be used\n"); @@ -145,6 +149,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { switch (method) { case ETH_PLUGIN_INIT_CONTRACT: + PRINTF("-- PLUGIN INIT CONTRACT --\n"); ((ethPluginInitContract_t *) parameter)->interfaceVersion = ETH_PLUGIN_INTERFACE_VERSION_1; ((ethPluginInitContract_t *) parameter)->result = ETH_PLUGIN_RESULT_UNAVAILABLE; @@ -157,6 +162,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { ((ethPluginInitContract_t *) parameter)->alias = dataContext.tokenContext.pluginName; break; case ETH_PLUGIN_PROVIDE_PARAMETER: + PRINTF("-- PLUGIN PROVIDE PARAMETER --\n"); ((ethPluginProvideParameter_t *) parameter)->result = ETH_PLUGIN_RESULT_UNAVAILABLE; ((ethPluginProvideParameter_t *) parameter)->pluginSharedRW = &pluginRW; ((ethPluginProvideParameter_t *) parameter)->pluginSharedRO = &pluginRO; @@ -164,6 +170,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { (uint8_t *) &dataContext.tokenContext.pluginContext; break; case ETH_PLUGIN_FINALIZE: + PRINTF("-- PLUGIN FINALIZE --\n"); ((ethPluginFinalize_t *) parameter)->result = ETH_PLUGIN_RESULT_UNAVAILABLE; ((ethPluginFinalize_t *) parameter)->pluginSharedRW = &pluginRW; ((ethPluginFinalize_t *) parameter)->pluginSharedRO = &pluginRO; @@ -171,6 +178,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { (uint8_t *) &dataContext.tokenContext.pluginContext; break; case ETH_PLUGIN_PROVIDE_TOKEN: + PRINTF("-- PLUGIN PROVIDE TOKEN --\n"); ((ethPluginProvideToken_t *) parameter)->result = ETH_PLUGIN_RESULT_UNAVAILABLE; ((ethPluginProvideToken_t *) parameter)->pluginSharedRW = &pluginRW; ((ethPluginProvideToken_t *) parameter)->pluginSharedRO = &pluginRO; @@ -178,6 +186,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { (uint8_t *) &dataContext.tokenContext.pluginContext; break; case ETH_PLUGIN_QUERY_CONTRACT_ID: + PRINTF("-- PLUGIN QUERY CONTRACT ID --\n"); ((ethQueryContractID_t *) parameter)->result = ETH_PLUGIN_RESULT_UNAVAILABLE; ((ethQueryContractID_t *) parameter)->pluginSharedRW = &pluginRW; ((ethQueryContractID_t *) parameter)->pluginSharedRO = &pluginRO; @@ -185,6 +194,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { (uint8_t *) &dataContext.tokenContext.pluginContext; break; case ETH_PLUGIN_QUERY_CONTRACT_UI: + PRINTF("-- PLUGIN QUERY CONTRACT UI --\n"); ((ethQueryContractUI_t *) parameter)->pluginSharedRW = &pluginRW; ((ethQueryContractUI_t *) parameter)->pluginSharedRO = &pluginRO; ((ethQueryContractUI_t *) parameter)->pluginContext = @@ -230,7 +240,6 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { PRINTF("method: %d\n", method); switch (method) { case ETH_PLUGIN_INIT_CONTRACT: - PRINTF("parameter result: %d\n", ((ethPluginInitContract_t *) parameter)->result); switch (((ethPluginInitContract_t *) parameter)->result) { case ETH_PLUGIN_RESULT_OK: break; @@ -263,6 +272,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { } break; case ETH_PLUGIN_PROVIDE_TOKEN: + PRINTF("RESULT: %d\n", ((ethPluginProvideToken_t *) parameter)->result); switch (((ethPluginProvideToken_t *) parameter)->result) { case ETH_PLUGIN_RESULT_OK: case ETH_PLUGIN_RESULT_FALLBACK: @@ -279,7 +289,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { } break; case ETH_PLUGIN_QUERY_CONTRACT_UI: - if (((ethQueryContractUI_t *) parameter)->result <= ETH_PLUGIN_RESULT_OK) { + if (((ethQueryContractUI_t *) parameter)->result <= ETH_PLUGIN_RESULT_UNSUCCESSFUL) { return ETH_PLUGIN_RESULT_UNAVAILABLE; } break; diff --git a/src/eth_plugin_handler.h b/src/eth_plugin_handler.h index 05d7649..8c86af3 100644 --- a/src/eth_plugin_handler.h +++ b/src/eth_plugin_handler.h @@ -7,9 +7,7 @@ void eth_plugin_prepare_provide_parameter(ethPluginProvideParameter_t *providePa uint8_t *parameter, uint32_t parameterOffset); void eth_plugin_prepare_finalize(ethPluginFinalize_t *finalize); -void eth_plugin_prepare_provide_token(ethPluginProvideToken_t *provideToken, - tokenDefinition_t *token1, - tokenDefinition_t *token2); +void eth_plugin_prepare_provide_token(ethPluginProvideToken_t *provideToken); void eth_plugin_prepare_query_contract_ID(ethQueryContractID_t *queryContractID, char *name, uint32_t nameLength, diff --git a/src/eth_plugin_interface.h b/src/eth_plugin_interface.h index 918645a..9c76b52 100644 --- a/src/eth_plugin_interface.h +++ b/src/eth_plugin_interface.h @@ -104,7 +104,8 @@ typedef struct ethPluginFinalize_t { uint8_t *tokenLookup2; uint8_t *amount; // set an uint256 pointer if uiType is UI_AMOUNT_ADDRESS - uint8_t *address; // set to a 20 bytes address pointer if uiType is UI_AMOUNT_ADDRESS + uint8_t *address; // set to the destination address if uiType is UI_AMOUNT_ADDRESS. Set to the + // user's address if uiType is UI_TYPE_GENERIC uint8_t uiType; uint8_t numScreens; // ignored if uiType is UI_AMOUNT_ADDRESS diff --git a/src/eth_plugin_ui.c b/src/eth_plugin_ui.c index 0f23262..cfd737c 100644 --- a/src/eth_plugin_ui.c +++ b/src/eth_plugin_ui.c @@ -23,7 +23,9 @@ void plugin_ui_get_id() { strings.tmp.tmp2, sizeof(strings.tmp.tmp2)); // Query the original contract for ID if it's not an internal alias - if (!eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_ID, (void *) &pluginQueryContractID)) { + eth_plugin_result_t status = + eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_ID, (void *) &pluginQueryContractID); + if (status != ETH_PLUGIN_RESULT_OK) { PRINTF("Plugin query contract ID call failed\n"); io_seproxyhal_touch_tx_cancel(NULL); } @@ -37,8 +39,10 @@ void plugin_ui_get_item() { sizeof(strings.tmp.tmp), strings.tmp.tmp2, sizeof(strings.tmp.tmp2)); - if (!eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_UI, (void *) &pluginQueryContractUI)) { - PRINTF("Plugin query contract UI call failed\n"); + eth_plugin_result_t status = + eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_UI, (void *) &pluginQueryContractUI); + if (status != ETH_PLUGIN_RESULT_OK) { + PRINTF("Plugin query contract UI call failed, got: %d\n", status); io_seproxyhal_touch_tx_cancel(NULL); } } diff --git a/src/main.c b/src/main.c index f1294f4..17b129c 100644 --- a/src/main.c +++ b/src/main.c @@ -394,7 +394,7 @@ void handleGetWalletId(volatile unsigned int *tx) { THROW(0x9000); } -#endif // HAVE_WALLET_ID_SDK +#endif // HAVE_WALLET_ID_SDK void handleApdu(unsigned int *flags, unsigned int *tx) { unsigned short sw = 0; @@ -409,7 +409,7 @@ void handleApdu(unsigned int *flags, unsigned int *tx) { return; } -#endif // HAVE_WALLET_ID_SDK +#endif // HAVE_WALLET_ID_SDK #ifdef HAVE_STARKWARE diff --git a/src_common/ethUtils.c b/src_common/ethUtils.c index 2c88821..8093428 100644 --- a/src_common/ethUtils.c +++ b/src_common/ethUtils.c @@ -124,7 +124,7 @@ void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3 } void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, - uint8_t *out, + char *out, cx_sha3_t *sha3Context, chain_config_t *chain_config) { uint8_t hashAddress[INT256_LENGTH]; diff --git a/src_common/ethUtils.h b/src_common/ethUtils.h index adc08a2..cb41acd 100644 --- a/src_common/ethUtils.h +++ b/src_common/ethUtils.h @@ -40,7 +40,7 @@ bool rlpCanDecode(uint8_t *buffer, uint32_t bufferLength, bool *valid); void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3_t *sha3Context); void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, - uint8_t *out, + char *out, cx_sha3_t *sha3Context, chain_config_t *chain_config); diff --git a/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c b/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c index c924084..4ab4e67 100644 --- a/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c +++ b/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c @@ -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); @@ -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 diff --git a/src_features/setExternalPlugin/cmd_setExternalPlugin.c b/src_features/setExternalPlugin/cmd_setExternalPlugin.c index 729df20..93c0b64 100644 --- a/src_features/setExternalPlugin/cmd_setExternalPlugin.c +++ b/src_features/setExternalPlugin/cmd_setExternalPlugin.c @@ -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 @@ -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; diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 33bc9ee..688bd34 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -239,12 +239,32 @@ void computeFees(char *displayBuffer, uint32_t displayBufferSize) { displayBuffer[tickerOffset + i] = '\0'; } +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; char *ticker = get_network_ticker(); ethPluginFinalize_t pluginFinalize; - tokenDefinition_t *token1 = NULL, *token2 = NULL; bool genericUI = true; // Verify the chain @@ -272,6 +292,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); @@ -281,22 +306,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"); @@ -331,9 +356,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 = (char *) token1->ticker; + if (pluginProvideToken.token1 != NULL) { + decimals = pluginProvideToken.token1->decimals; + ticker = (char *) pluginProvideToken.token1->ticker; } break; default: