Merge pull request #600 from LedgerHQ/feat/apa/new_app_policies

New app policies
This commit is contained in:
Charles-Edouard de la Vergne
2024-06-26 13:44:39 +02:00
committed by GitHub
261 changed files with 367 additions and 402 deletions

View File

@@ -5,27 +5,24 @@ from typing import Union
class SettingID(Enum): class SettingID(Enum):
BLIND_SIGNING = auto()
DEBUG_DATA = auto()
NONCE = auto()
VERBOSE_EIP712 = auto()
VERBOSE_ENS = auto() VERBOSE_ENS = auto()
VERBOSE_EIP712 = auto()
NONCE = auto()
DEBUG_DATA = auto()
def get_device_settings(device: str) -> list[SettingID]: def get_device_settings(device: str) -> list[SettingID]:
if device == "nanos": if device == "nanos":
return [ return [
SettingID.BLIND_SIGNING, SettingID.NONCE,
SettingID.DEBUG_DATA, SettingID.DEBUG_DATA,
SettingID.NONCE
] ]
if device in ("nanox", "nanosp", "stax", "flex"): if device in ("nanox", "nanosp", "stax", "flex"):
return [ return [
SettingID.BLIND_SIGNING, SettingID.VERBOSE_ENS,
SettingID.DEBUG_DATA,
SettingID.NONCE,
SettingID.VERBOSE_EIP712, SettingID.VERBOSE_EIP712,
SettingID.VERBOSE_ENS SettingID.NONCE,
SettingID.DEBUG_DATA,
] ]
return [] return []

View File

@@ -95,7 +95,6 @@ void __attribute__((noreturn)) handle_swap_sign_transaction(const chain_config_t
if (N_storage.initialized != 0x01) { if (N_storage.initialized != 0x01) {
internalStorage_t storage; internalStorage_t storage;
storage.dataAllowed = 0x00;
storage.contractDetails = 0x00; storage.contractDetails = 0x00;
storage.initialized = 0x01; storage.initialized = 0x01;
storage.displayNonce = 0x00; storage.displayNonce = 0x00;

View File

@@ -39,7 +39,6 @@ unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
void ui_idle(void); void ui_idle(void);
uint32_t set_result_get_publicKey(void); uint32_t set_result_get_publicKey(void);
void finalizeParsing(bool);
tmpCtx_t tmpCtx; tmpCtx_t tmpCtx;
txContext_t txContext; txContext_t txContext;
@@ -549,11 +548,6 @@ __attribute__((noreturn)) void coin_main(libargs_t *args) {
if (!N_storage.initialized) { if (!N_storage.initialized) {
internalStorage_t storage; internalStorage_t storage;
#ifdef HAVE_ALLOW_DATA
storage.dataAllowed = true;
#else
storage.dataAllowed = false;
#endif
storage.contractDetails = false; storage.contractDetails = false;
storage.displayNonce = false; storage.displayNonce = false;
#ifdef HAVE_EIP712_FULL_SUPPORT #ifdef HAVE_EIP712_FULL_SUPPORT

View File

@@ -30,7 +30,6 @@ typedef struct bip32_path_t {
} bip32_path_t; } bip32_path_t;
typedef struct internalStorage_t { typedef struct internalStorage_t {
bool dataAllowed;
bool contractDetails; bool contractDetails;
bool displayNonce; bool displayNonce;
#ifdef HAVE_EIP712_FULL_SUPPORT #ifdef HAVE_EIP712_FULL_SUPPORT

View File

@@ -24,4 +24,3 @@ unsigned int io_seproxyhal_touch_privacy_cancel(const bagl_element_t *e);
void ui_warning_contract_data(void); void ui_warning_contract_data(void);
void io_seproxyhal_send_status(uint32_t sw); void io_seproxyhal_send_status(uint32_t sw);
void finalizeParsing(bool direct);

View File

@@ -13,7 +13,7 @@ void ui_idle(void) {
} }
void ui_warning_contract_data(void) { void ui_warning_contract_data(void) {
ux_flow_init(0, ux_warning_contract_data_flow, NULL); ux_flow_init(0, ux_blind_signing_flow, NULL);
} }
void ui_display_public_eth2(void) { void ui_display_public_eth2(void) {

View File

@@ -2,6 +2,7 @@
#include "ui_callbacks.h" #include "ui_callbacks.h"
#include "common_ui.h" #include "common_ui.h"
#include "common_utils.h" #include "common_utils.h"
#include "feature_signTx.h"
#define ENABLED_STR "Enabled" #define ENABLED_STR "Enabled"
#define DISABLED_STR "Disabled" #define DISABLED_STR "Disabled"
@@ -9,16 +10,14 @@
// Reuse the strings.common.fullAmount buffer for settings displaying. // Reuse the strings.common.fullAmount buffer for settings displaying.
// No risk of collision as this buffer is unused in the settings menu // No risk of collision as this buffer is unused in the settings menu
#define SETTING_BLIND_SIGNING_STATE (strings.common.fullAmount) #define SETTING_VERBOSE_DOMAIN_NAME_STATE (strings.common.fullAmount + (BUF_INCREMENT * 0))
#define SETTING_DISPLAY_DATA_STATE (strings.common.fullAmount + (BUF_INCREMENT * 1)) #define SETTING_VERBOSE_EIP712_STATE (strings.common.fullAmount + (BUF_INCREMENT * 1))
#define SETTING_DISPLAY_NONCE_STATE (strings.common.fullAmount + (BUF_INCREMENT * 2)) #define SETTING_DISPLAY_NONCE_STATE (strings.common.fullAmount + (BUF_INCREMENT * 2))
#define SETTING_VERBOSE_EIP712_STATE (strings.common.fullAmount + (BUF_INCREMENT * 3)) #define SETTING_DISPLAY_DATA_STATE (strings.common.fullAmount + (BUF_INCREMENT * 3))
#define SETTING_VERBOSE_DOMAIN_NAME_STATE (strings.common.fullAmount + (BUF_INCREMENT * 4))
#define BOOL_TO_STATE_STR(b) (b ? ENABLED_STR : DISABLED_STR) #define BOOL_TO_STATE_STR(b) (b ? ENABLED_STR : DISABLED_STR)
static void display_settings(const ux_flow_step_t* const start_step); static void display_settings(const ux_flow_step_t* const start_step);
static void switch_settings_blind_signing(void);
static void switch_settings_display_data(void); static void switch_settings_display_data(void);
static void switch_settings_display_nonce(void); static void switch_settings_display_nonce(void);
#ifdef HAVE_EIP712_FULL_SUPPORT #ifdef HAVE_EIP712_FULL_SUPPORT
@@ -71,45 +70,31 @@ UX_FLOW(ux_idle_flow,
FLOW_LOOP); FLOW_LOOP);
// clang-format off // clang-format off
#ifdef HAVE_DOMAIN_NAME
UX_STEP_CB( UX_STEP_CB(
ux_settings_flow_blind_signing_step, ux_settings_flow_verbose_domain_name_step,
#ifdef TARGET_NANOS
bnnn_paging,
#else
bnnn, bnnn,
#endif switch_settings_verbose_domain_name(),
switch_settings_blind_signing(),
{ {
#ifdef TARGET_NANOS "ENS addresses",
.title = "Blind signing", "Displays resolved",
.text = "addresses from ENS",
#else SETTING_VERBOSE_DOMAIN_NAME_STATE
"Blind signing",
"Transaction",
"blind signing",
#endif
SETTING_BLIND_SIGNING_STATE
}); });
#endif // HAVE_DOMAIN_NAME
#ifdef HAVE_EIP712_FULL_SUPPORT
UX_STEP_CB( UX_STEP_CB(
ux_settings_flow_display_data_step, ux_settings_flow_verbose_eip712_step,
#ifdef TARGET_NANOS
bnnn_paging,
#else
bnnn, bnnn,
#endif switch_settings_verbose_eip712(),
switch_settings_display_data(),
{ {
#ifdef TARGET_NANOS "Raw messages",
.title = "Debug data", "Displays raw content",
.text = "from EIP712 messages",
#else SETTING_VERBOSE_EIP712_STATE
"Debug data",
"Show contract data",
"details",
#endif
SETTING_DISPLAY_DATA_STATE
}); });
#endif // HAVE_EIP712_FULL_SUPPORT
UX_STEP_CB( UX_STEP_CB(
ux_settings_flow_display_nonce_step, ux_settings_flow_display_nonce_step,
@@ -125,38 +110,31 @@ UX_STEP_CB(
.text = .text =
#else #else
"Nonce", "Nonce",
"Show account nonce", "Displays nonce",
"in transactions", "in transactions",
#endif #endif
SETTING_DISPLAY_NONCE_STATE SETTING_DISPLAY_NONCE_STATE
}); });
#ifdef HAVE_EIP712_FULL_SUPPORT
UX_STEP_CB( UX_STEP_CB(
ux_settings_flow_verbose_eip712_step, ux_settings_flow_display_data_step,
#ifdef TARGET_NANOS
bnnn_paging,
#else
bnnn, bnnn,
switch_settings_verbose_eip712(), #endif
switch_settings_display_data(),
{ {
"Verbose EIP-712", #ifdef TARGET_NANOS
"Ignore filtering &", .title = "Debug data",
"display raw content", .text =
SETTING_VERBOSE_EIP712_STATE #else
"Debug contracts",
"Displays contract",
"data details",
#endif
SETTING_DISPLAY_DATA_STATE
}); });
#endif // HAVE_EIP712_FULL_SUPPORT
#ifdef HAVE_DOMAIN_NAME
UX_STEP_CB(
ux_settings_flow_verbose_domain_name_step,
bnnn,
switch_settings_verbose_domain_name(),
{
"Verbose domains",
"Show",
"resolved address",
SETTING_VERBOSE_DOMAIN_NAME_STATE
});
#endif // HAVE_DOMAIN_NAME
UX_STEP_CB( UX_STEP_CB(
ux_settings_flow_back_step, ux_settings_flow_back_step,
@@ -169,19 +147,17 @@ UX_STEP_CB(
// clang-format on // clang-format on
UX_FLOW(ux_settings_flow, UX_FLOW(ux_settings_flow,
&ux_settings_flow_blind_signing_step,
&ux_settings_flow_display_data_step,
&ux_settings_flow_display_nonce_step,
#ifdef HAVE_EIP712_FULL_SUPPORT
&ux_settings_flow_verbose_eip712_step,
#endif // HAVE_EIP712_FULL_SUPPORT
#ifdef HAVE_DOMAIN_NAME #ifdef HAVE_DOMAIN_NAME
&ux_settings_flow_verbose_domain_name_step, &ux_settings_flow_verbose_domain_name_step,
#endif // HAVE_DOMAIN_NAME #endif // HAVE_DOMAIN_NAME
#ifdef HAVE_EIP712_FULL_SUPPORT
&ux_settings_flow_verbose_eip712_step,
#endif // HAVE_EIP712_FULL_SUPPORT
&ux_settings_flow_display_nonce_step,
&ux_settings_flow_display_data_step,
&ux_settings_flow_back_step); &ux_settings_flow_back_step);
static void display_settings(const ux_flow_step_t* const start_step) { static void display_settings(const ux_flow_step_t* const start_step) {
strlcpy(SETTING_BLIND_SIGNING_STATE, BOOL_TO_STATE_STR(N_storage.dataAllowed), BUF_INCREMENT);
strlcpy(SETTING_DISPLAY_DATA_STATE, strlcpy(SETTING_DISPLAY_DATA_STATE,
BOOL_TO_STATE_STR(N_storage.contractDetails), BOOL_TO_STATE_STR(N_storage.contractDetails),
BUF_INCREMENT); BUF_INCREMENT);
@@ -206,10 +182,6 @@ static void toggle_setting(volatile bool* setting, const ux_flow_step_t* ui_step
display_settings(ui_step); display_settings(ui_step);
} }
static void switch_settings_blind_signing(void) {
toggle_setting(&N_storage.dataAllowed, &ux_settings_flow_blind_signing_step);
}
static void switch_settings_display_data(void) { static void switch_settings_display_data(void) {
toggle_setting(&N_storage.contractDetails, &ux_settings_flow_display_data_step); toggle_setting(&N_storage.contractDetails, &ux_settings_flow_display_data_step);
} }
@@ -232,26 +204,76 @@ static void switch_settings_verbose_domain_name(void) {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// clang-format off // clang-format off
UX_STEP_NOCB(
ux_blind_signing_warning_step,
pbb,
{
&C_icon_warning,
#ifdef TARGET_NANOS #ifdef TARGET_NANOS
UX_STEP_CB( "Transaction",
ux_warning_contract_data_step, "not trusted",
bnnn_paging,
ui_idle(),
{
"Error",
"Blind signing must be enabled in Settings",
});
#else #else
UX_STEP_CB( "This transaction",
ux_warning_contract_data_step, "cannot be trusted",
pnn, #endif
ui_idle(), });
#ifndef TARGET_NANOS
UX_STEP_NOCB(
ux_blind_signing_text1_step,
nnnn,
{ {
&C_icon_crossmark, "Your Ledger cannot",
"Blind signing must be", "decode this",
"enabled in Settings", "transaction. If you",
"sign it, you could",
});
UX_STEP_NOCB(
ux_blind_signing_text2_step,
nnnn,
{
"be authorizing",
"malicious actions",
"that can drain your",
"wallet.",
}); });
#endif #endif
UX_STEP_NOCB(
ux_blind_signing_link_step,
nn,
{
"Learn more:",
"ledger.com/e8",
});
UX_STEP_CB(
ux_blind_signing_accept_step,
pbb,
start_signature_flow(),
{
&C_icon_validate_14,
#ifdef TARGET_NANOS
"Accept risk",
"and review",
#else
"Accept risk and",
"review transaction",
#endif
});
UX_STEP_CB(
ux_blind_signing_reject_step,
pb,
report_finalize_error(),
{
&C_icon_crossmark,
"Reject",
});
// clang-format on // clang-format on
UX_FLOW(ux_warning_contract_data_flow, &ux_warning_contract_data_step); UX_FLOW(ux_blind_signing_flow,
&ux_blind_signing_warning_step,
#ifndef TARGET_NANOS
&ux_blind_signing_text1_step,
&ux_blind_signing_text2_step,
#endif
&ux_blind_signing_link_step,
&ux_blind_signing_accept_step,
&ux_blind_signing_reject_step);

View File

@@ -8,7 +8,7 @@
extern const ux_flow_step_t* const ux_idle_flow[]; extern const ux_flow_step_t* const ux_idle_flow[];
extern const ux_flow_step_t* const ux_warning_contract_data_flow[]; extern const ux_flow_step_t* const ux_blind_signing_flow[];
extern const ux_flow_step_t* const ux_settings_flow[]; extern const ux_flow_step_t* const ux_settings_flow[];

View File

@@ -199,12 +199,12 @@ UX_STEP_NOCB(
.text = strings.common.nonce, .text = strings.common.nonce,
}); });
UX_STEP_NOCB(ux_approval_blind_signing_warning_step, UX_STEP_NOCB(ux_approval_blind_signing_reminder_step,
pbb, pbb,
{ {
&C_icon_warning, &C_icon_warning,
"Blind", "You accepted",
"Signing", "the risks",
}); });
// clang-format on // clang-format on
@@ -214,10 +214,6 @@ void ux_approve_tx(bool fromPlugin) {
int step = 0; int step = 0;
ux_approval_tx_flow[step++] = &ux_approval_review_step; ux_approval_tx_flow[step++] = &ux_approval_review_step;
if (!fromPlugin && tmpContent.txContent.dataPresent && !N_storage.contractDetails) {
ux_approval_tx_flow[step++] = &ux_approval_blind_signing_warning_step;
}
if (fromPlugin) { if (fromPlugin) {
// Add the special dynamic display logic // Add the special dynamic display logic
ux_approval_tx_flow[step++] = &ux_plugin_approval_id_step; ux_approval_tx_flow[step++] = &ux_plugin_approval_id_step;
@@ -260,6 +256,9 @@ void ux_approve_tx(bool fromPlugin) {
} }
ux_approval_tx_flow[step++] = &ux_approval_fees_step; ux_approval_tx_flow[step++] = &ux_approval_fees_step;
if (!fromPlugin && tmpContent.txContent.dataPresent && !N_storage.contractDetails) {
ux_approval_tx_flow[step++] = &ux_approval_blind_signing_reminder_step;
}
ux_approval_tx_flow[step++] = &ux_approval_accept_step; ux_approval_tx_flow[step++] = &ux_approval_accept_step;
ux_approval_tx_flow[step++] = &ux_approval_reject_step; ux_approval_tx_flow[step++] = &ux_approval_reject_step;
ux_approval_tx_flow[step++] = FLOW_END_STEP; ux_approval_tx_flow[step++] = FLOW_END_STEP;

View File

@@ -12,8 +12,7 @@ void handleGetAppConfiguration(uint8_t p1,
UNUSED(workBuffer); UNUSED(workBuffer);
UNUSED(dataLength); UNUSED(dataLength);
UNUSED(flags); UNUSED(flags);
G_io_apdu_buffer[0] = (N_storage.dataAllowed ? APP_FLAG_DATA_ALLOWED : 0x00); G_io_apdu_buffer[0] = APP_FLAG_EXTERNAL_TOKEN_NEEDED;
G_io_apdu_buffer[0] |= APP_FLAG_EXTERNAL_TOKEN_NEEDED;
G_io_apdu_buffer[1] = MAJOR_VERSION; G_io_apdu_buffer[1] = MAJOR_VERSION;
G_io_apdu_buffer[2] = MINOR_VERSION; G_io_apdu_buffer[2] = MINOR_VERSION;
G_io_apdu_buffer[3] = PATCH_VERSION; G_io_apdu_buffer[3] = PATCH_VERSION;

View File

@@ -88,7 +88,7 @@ void handleSign(uint8_t p1,
} }
if (txResult == USTREAM_FINISHED) { if (txResult == USTREAM_FINISHED) {
finalizeParsing(false); finalizeParsing();
} }
*flags |= IO_ASYNCH_REPLY; *flags |= IO_ASYNCH_REPLY;

View File

@@ -11,9 +11,11 @@ typedef enum {
} plugin_ui_state_t; } plugin_ui_state_t;
customStatus_e customProcessor(txContext_t *context); customStatus_e customProcessor(txContext_t *context);
void finalizeParsing(bool direct); void finalizeParsing();
void prepareFeeDisplay(); void prepareFeeDisplay();
void prepareNetworkDisplay(); void prepareNetworkDisplay();
void ux_approve_tx(bool fromPlugin); void ux_approve_tx(bool fromPlugin);
void report_finalize_error(void);
void start_signature_flow(void);
#endif // _SIGN_TX_H_ #endif // _SIGN_TX_H_

View File

@@ -14,6 +14,8 @@
#define ERR_SILENT_MODE_CHECK_FAILED 0x6001 #define ERR_SILENT_MODE_CHECK_FAILED 0x6001
static bool g_use_standard_ui;
static uint32_t splitBinaryParameterPart(char *result, size_t result_size, uint8_t *parameter) { static uint32_t splitBinaryParameterPart(char *result, size_t result_size, uint8_t *parameter) {
uint32_t i; uint32_t i;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
@@ -82,11 +84,6 @@ customStatus_e customProcessor(txContext_t *context) {
uint32_t copySize; uint32_t copySize;
uint32_t fieldPos = context->currentFieldPos; uint32_t fieldPos = context->currentFieldPos;
if (fieldPos == 0) { // not reached if a plugin is available if (fieldPos == 0) { // not reached if a plugin is available
if (!N_storage.dataAllowed) {
PRINTF("Data field forbidden\n");
ui_warning_contract_data();
return CUSTOM_FAULT;
}
if (!N_storage.contractDetails) { if (!N_storage.contractDetails) {
return CUSTOM_NOT_HANDLED; return CUSTOM_NOT_HANDLED;
} }
@@ -177,14 +174,10 @@ customStatus_e customProcessor(txContext_t *context) {
return CUSTOM_NOT_HANDLED; return CUSTOM_NOT_HANDLED;
} }
void reportFinalizeError(bool direct) { void report_finalize_error(void) {
reset_app_context(); reset_app_context();
if (direct) { io_seproxyhal_send_status(APDU_RESPONSE_INVALID_DATA);
THROW(0x6A80); ui_idle();
} else {
io_seproxyhal_send_status(0x6A80);
ui_idle();
}
} }
static void address_to_string(uint8_t *in, static void address_to_string(uint8_t *in,
@@ -317,7 +310,7 @@ static int strcasecmp_workaround(const char *str1, const char *str2) {
return 0; return 0;
} }
__attribute__((noinline)) static bool finalize_parsing_helper(bool direct, bool *use_standard_UI) { __attribute__((noinline)) static bool finalize_parsing_helper(void) {
char displayBuffer[50]; char displayBuffer[50];
uint8_t decimals = WEI_TO_ETHER; uint8_t decimals = WEI_TO_ETHER;
uint64_t chain_id = get_tx_chain_id(); uint64_t chain_id = get_tx_chain_id();
@@ -332,10 +325,8 @@ __attribute__((noinline)) static bool finalize_parsing_helper(bool direct, bool
if (chainConfig->chainId != id) { if (chainConfig->chainId != id) {
PRINTF("Invalid chainID %u expected %u\n", id, chainConfig->chainId); PRINTF("Invalid chainID %u expected %u\n", id, chainConfig->chainId);
reset_app_context(); reset_app_context();
reportFinalizeError(direct); report_finalize_error();
if (!direct) { return false;
return false;
}
} }
} }
// Store the hash // Store the hash
@@ -363,10 +354,8 @@ __attribute__((noinline)) static bool finalize_parsing_helper(bool direct, bool
if (!eth_plugin_call(ETH_PLUGIN_FINALIZE, (void *) &pluginFinalize)) { if (!eth_plugin_call(ETH_PLUGIN_FINALIZE, (void *) &pluginFinalize)) {
PRINTF("Plugin finalize call failed\n"); PRINTF("Plugin finalize call failed\n");
reportFinalizeError(direct); report_finalize_error();
if (!direct) { return false;
return false;
}
} }
// Lookup tokens if requested // Lookup tokens if requested
ethPluginProvideInfo_t pluginProvideInfo; ethPluginProvideInfo_t pluginProvideInfo;
@@ -389,10 +378,8 @@ __attribute__((noinline)) static bool finalize_parsing_helper(bool direct, bool
if (eth_plugin_call(ETH_PLUGIN_PROVIDE_INFO, (void *) &pluginProvideInfo) <= if (eth_plugin_call(ETH_PLUGIN_PROVIDE_INFO, (void *) &pluginProvideInfo) <=
ETH_PLUGIN_RESULT_UNSUCCESSFUL) { ETH_PLUGIN_RESULT_UNSUCCESSFUL) {
PRINTF("Plugin provide token call failed\n"); PRINTF("Plugin provide token call failed\n");
reportFinalizeError(direct); report_finalize_error();
if (!direct) { return false;
return false;
}
} }
pluginFinalize.result = pluginProvideInfo.result; pluginFinalize.result = pluginProvideInfo.result;
} }
@@ -401,7 +388,7 @@ __attribute__((noinline)) static bool finalize_parsing_helper(bool direct, bool
switch (pluginFinalize.uiType) { switch (pluginFinalize.uiType) {
case ETH_UI_TYPE_GENERIC: case ETH_UI_TYPE_GENERIC:
// Use the dedicated ETH plugin UI // Use the dedicated ETH plugin UI
*use_standard_UI = false; g_use_standard_ui = false;
tmpContent.txContent.dataPresent = false; tmpContent.txContent.dataPresent = false;
// Add the number of screens + the number of additional screens to get the total // Add the number of screens + the number of additional screens to get the total
// number of screens needed. // number of screens needed.
@@ -410,14 +397,12 @@ __attribute__((noinline)) static bool finalize_parsing_helper(bool direct, bool
break; break;
case ETH_UI_TYPE_AMOUNT_ADDRESS: case ETH_UI_TYPE_AMOUNT_ADDRESS:
// Use the standard ETH UI as this plugin uses the amount/address UI // Use the standard ETH UI as this plugin uses the amount/address UI
*use_standard_UI = true; g_use_standard_ui = true;
tmpContent.txContent.dataPresent = false; tmpContent.txContent.dataPresent = false;
if ((pluginFinalize.amount == NULL) || (pluginFinalize.address == NULL)) { if ((pluginFinalize.amount == NULL) || (pluginFinalize.address == NULL)) {
PRINTF("Incorrect amount/address set by plugin\n"); PRINTF("Incorrect amount/address set by plugin\n");
reportFinalizeError(direct); report_finalize_error();
if (!direct) { return false;
return false;
}
} }
memmove(tmpContent.txContent.value.value, pluginFinalize.amount, 32); memmove(tmpContent.txContent.value.value, pluginFinalize.amount, 32);
tmpContent.txContent.value.length = 32; tmpContent.txContent.value.length = 32;
@@ -430,10 +415,8 @@ __attribute__((noinline)) static bool finalize_parsing_helper(bool direct, bool
break; break;
default: default:
PRINTF("ui type %d not supported\n", pluginFinalize.uiType); PRINTF("ui type %d not supported\n", pluginFinalize.uiType);
reportFinalizeError(direct); report_finalize_error();
if (!direct) { return false;
return false;
}
} }
} }
} }
@@ -448,21 +431,13 @@ __attribute__((noinline)) static bool finalize_parsing_helper(bool direct, bool
} }
// User has just validated a swap but ETH received apdus about a non standard plugin / contract // User has just validated a swap but ETH received apdus about a non standard plugin / contract
if (G_called_from_swap && !*use_standard_UI) { if (G_called_from_swap && !g_use_standard_ui) {
PRINTF("ERR_SILENT_MODE_CHECK_FAILED, G_called_from_swap\n"); PRINTF("ERR_SILENT_MODE_CHECK_FAILED, G_called_from_swap\n");
THROW(ERR_SILENT_MODE_CHECK_FAILED); THROW(ERR_SILENT_MODE_CHECK_FAILED);
} }
if (tmpContent.txContent.dataPresent && !N_storage.dataAllowed) {
reportFinalizeError(direct);
ui_warning_contract_data();
if (!direct) {
return false;
}
}
// Prepare destination address and amount to display // Prepare destination address and amount to display
if (*use_standard_UI) { if (g_use_standard_ui) {
// Format the address in a temporary buffer, if in swap case compare it with validated // Format the address in a temporary buffer, if in swap case compare it with validated
// address, else commit it // address, else commit it
address_to_string(tmpContent.txContent.destination, address_to_string(tmpContent.txContent.destination,
@@ -541,23 +516,32 @@ end:
return false; return false;
} }
void finalizeParsing(bool direct) { void start_signature_flow(void) {
bool use_standard_UI = true; if (g_use_standard_ui) {
ux_approve_tx(false);
} else {
dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE;
dataContext.tokenContext.pluginUiCurrentItem = 0;
ux_approve_tx(true);
}
}
if (!finalize_parsing_helper(direct, &use_standard_UI)) { void finalizeParsing(void) {
g_use_standard_ui = true;
if (!finalize_parsing_helper()) {
return; return;
} }
// If called from swap, the user has already validated a standard transaction // If called from swap, the user has already validated a standard transaction
// And we have already checked the fields of this transaction above // And we have already checked the fields of this transaction above
if (G_called_from_swap && use_standard_UI) { if (G_called_from_swap && g_use_standard_ui) {
io_seproxyhal_touch_tx_ok(NULL); io_seproxyhal_touch_tx_ok(NULL);
} else { } else {
if (use_standard_UI) { // If blind-signing detected, start the warning flow beforehand
ux_approve_tx(false); if (tmpContent.txContent.dataPresent) {
ui_warning_contract_data();
} else { } else {
dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE; start_signature_flow();
dataContext.tokenContext.pluginUiCurrentItem = 0;
ux_approve_tx(true);
} }
} }
} }

View File

@@ -4,6 +4,7 @@
#include "common_utils.h" #include "common_utils.h"
#include "common_ui.h" #include "common_ui.h"
#include "handle_swap_sign_transaction.h" #include "handle_swap_sign_transaction.h"
#include "feature_signTx.h"
unsigned int io_seproxyhal_touch_tx_ok(__attribute__((unused)) const bagl_element_t *e) { unsigned int io_seproxyhal_touch_tx_ok(__attribute__((unused)) const bagl_element_t *e) {
uint32_t info = 0; uint32_t info = 0;
@@ -109,7 +110,7 @@ unsigned int io_seproxyhal_touch_data_ok(__attribute__((unused)) const bagl_elem
} }
if (txResult == USTREAM_FINISHED) { if (txResult == USTREAM_FINISHED) {
finalizeParsing(false); finalizeParsing();
} }
return 0; return 0;

View File

@@ -1,5 +1,5 @@
#include <ctype.h> #include <ctype.h>
#include <nbgl_page.h> #include "nbgl_page.h"
#include "shared_context.h" #include "shared_context.h"
#include "ui_callbacks.h" #include "ui_callbacks.h"
#include "ui_nbgl.h" #include "ui_nbgl.h"
@@ -25,7 +25,6 @@ static char msg_buffer[MAX_PLUGIN_ITEMS][VALUE_MAX_LEN];
struct tx_approval_context_t { struct tx_approval_context_t {
bool fromPlugin; bool fromPlugin;
bool blindSigning;
bool displayNetwork; bool displayNetwork;
#ifdef HAVE_DOMAIN_NAME #ifdef HAVE_DOMAIN_NAME
bool domain_name_match; bool domain_name_match;
@@ -174,7 +173,13 @@ static void reviewCommon(void) {
pairsList.nbPairs = setTagValuePairs(); pairsList.nbPairs = setTagValuePairs();
pairsList.pairs = pairs; pairsList.pairs = pairs;
nbgl_operationType_t op = TYPE_TRANSACTION;
#if API_LEVEL >= 19
if (tmpContent.txContent.dataPresent) {
op |= BLIND_OPERATION;
}
#endif
if (tx_approval_context.fromPlugin) { if (tx_approval_context.fromPlugin) {
uint32_t buf_size = SHARED_BUFFER_SIZE / 2; uint32_t buf_size = SHARED_BUFFER_SIZE / 2;
char op_name[sizeof(strings.common.fullAmount)]; char op_name[sizeof(strings.common.fullAmount)];
@@ -195,7 +200,7 @@ static void reviewCommon(void) {
(pluginType == EXTERNAL ? "on " : ""), (pluginType == EXTERNAL ? "on " : ""),
strings.common.toAddress); strings.common.toAddress);
nbgl_useCaseReview(TYPE_TRANSACTION, nbgl_useCaseReview(op,
&pairsList, &pairsList,
get_tx_icon(), get_tx_icon(),
g_stax_shared_buffer, g_stax_shared_buffer,
@@ -203,7 +208,7 @@ static void reviewCommon(void) {
g_stax_shared_buffer + buf_size, g_stax_shared_buffer + buf_size,
reviewChoice); reviewChoice);
} else { } else {
nbgl_useCaseReview(TYPE_TRANSACTION, nbgl_useCaseReview(op,
&pairsList, &pairsList,
get_tx_icon(), get_tx_icon(),
REVIEW("transaction"), REVIEW("transaction"),
@@ -224,8 +229,6 @@ void blind_confirm_cb(bool confirm) {
void ux_approve_tx(bool fromPlugin) { void ux_approve_tx(bool fromPlugin) {
memset(&tx_approval_context, 0, sizeof(tx_approval_context)); memset(&tx_approval_context, 0, sizeof(tx_approval_context));
tx_approval_context.blindSigning =
!fromPlugin && tmpContent.txContent.dataPresent && !N_storage.contractDetails;
tx_approval_context.fromPlugin = fromPlugin; tx_approval_context.fromPlugin = fromPlugin;
tx_approval_context.displayNetwork = false; tx_approval_context.displayNetwork = false;
@@ -234,16 +237,5 @@ void ux_approve_tx(bool fromPlugin) {
tx_approval_context.displayNetwork = true; tx_approval_context.displayNetwork = true;
} }
if (tx_approval_context.blindSigning) { reviewCommon();
nbgl_useCaseChoice(&C_Important_Circle_64px,
"Blind Signing",
"This transaction cannot be securely interpreted by "
"your Ledger device.\nIt might put "
"your assets at risk.",
"Continue",
"Cancel",
blind_confirm_cb);
} else {
reviewCommon();
}
} }

View File

@@ -9,8 +9,7 @@
#define SETTING_CONTENTS_NB 1 #define SETTING_CONTENTS_NB 1
enum { enum {
BLIND_SIGNING_TOKEN = FIRST_USER_TOKEN, DEBUG_TOKEN = FIRST_USER_TOKEN,
DEBUG_TOKEN,
NONCE_TOKEN, NONCE_TOKEN,
#ifdef HAVE_EIP712_FULL_SUPPORT #ifdef HAVE_EIP712_FULL_SUPPORT
EIP712_VERBOSE_TOKEN, EIP712_VERBOSE_TOKEN,
@@ -21,23 +20,22 @@ enum {
}; };
enum { enum {
BLIND_SIGNING_ID = 0,
DEBUG_ID,
NONCE_ID,
#ifdef HAVE_EIP712_FULL_SUPPORT
EIP712_VERBOSE_ID,
#endif
#ifdef HAVE_DOMAIN_NAME #ifdef HAVE_DOMAIN_NAME
DOMAIN_NAME_VERBOSE_ID, DOMAIN_NAME_VERBOSE_ID,
#endif #endif
#ifdef HAVE_EIP712_FULL_SUPPORT
EIP712_VERBOSE_ID,
#endif
NONCE_ID,
DEBUG_ID,
SETTINGS_SWITCHES_NB SETTINGS_SWITCHES_NB
}; };
static uint8_t initSettingPage; static uint8_t initSettingPage;
// settings definition // settings definition
static const char* const infoTypes[SETTING_INFO_NB] = {"Version", APPNAME " App"}; static const char* const infoTypes[SETTING_INFO_NB] = {"Version", "Developer"};
static const char* const infoContents[SETTING_INFO_NB] = {APPVERSION, "(c) " BUILD_YEAR " Ledger"}; static const char* const infoContents[SETTING_INFO_NB] = {APPVERSION, "Ledger"};
static nbgl_contentInfoList_t infoList = {0}; static nbgl_contentInfoList_t infoList = {0};
static nbgl_contentSwitch_t switches[SETTINGS_SWITCHES_NB] = {0}; static nbgl_contentSwitch_t switches[SETTINGS_SWITCHES_NB] = {0};
@@ -51,11 +49,6 @@ static void controlsCallback(int token, uint8_t index, int page) {
initSettingPage = page; initSettingPage = page;
switch (token) { switch (token) {
case BLIND_SIGNING_TOKEN:
value = (N_storage.dataAllowed ? 0 : 1);
switches[BLIND_SIGNING_ID].initState = (nbgl_state_t) value;
nvm_write((void*) &N_storage.dataAllowed, (void*) &value, sizeof(uint8_t));
break;
case DEBUG_TOKEN: case DEBUG_TOKEN:
value = (N_storage.contractDetails ? 0 : 1); value = (N_storage.contractDetails ? 0 : 1);
switches[DEBUG_ID].initState = (nbgl_state_t) value; switches[DEBUG_ID].initState = (nbgl_state_t) value;
@@ -84,40 +77,34 @@ static void controlsCallback(int token, uint8_t index, int page) {
} }
void ui_menu_settings(void) { void ui_menu_settings(void) {
switches[BLIND_SIGNING_ID].initState = N_storage.dataAllowed ? ON_STATE : OFF_STATE; #ifdef HAVE_DOMAIN_NAME
switches[BLIND_SIGNING_ID].text = "Blind signing"; switches[DOMAIN_NAME_VERBOSE_ID].initState =
switches[BLIND_SIGNING_ID].subText = "Enable transaction blind\nsigning"; N_storage.verbose_domain_name ? ON_STATE : OFF_STATE;
switches[BLIND_SIGNING_ID].token = BLIND_SIGNING_TOKEN; switches[DOMAIN_NAME_VERBOSE_ID].text = "ENS addresses";
switches[BLIND_SIGNING_ID].tuneId = TUNE_TAP_CASUAL; switches[DOMAIN_NAME_VERBOSE_ID].subText = "Displays the resolved address of ENS domains.";
switches[DOMAIN_NAME_VERBOSE_ID].token = DOMAIN_NAME_VERBOSE_TOKEN;
switches[DEBUG_ID].initState = N_storage.contractDetails ? ON_STATE : OFF_STATE; switches[DOMAIN_NAME_VERBOSE_ID].tuneId = TUNE_TAP_CASUAL;
switches[DEBUG_ID].text = "Debug"; #endif // HAVE_DOMAIN_NAME
switches[DEBUG_ID].subText = "Display contract data\ndetails";
switches[DEBUG_ID].token = DEBUG_TOKEN;
switches[DEBUG_ID].tuneId = TUNE_TAP_CASUAL;
switches[NONCE_ID].initState = N_storage.displayNonce ? ON_STATE : OFF_STATE;
switches[NONCE_ID].text = "Nonce";
switches[NONCE_ID].subText = "Display account nonce\nin transaction";
switches[NONCE_ID].token = NONCE_TOKEN;
switches[NONCE_ID].tuneId = TUNE_TAP_CASUAL;
#ifdef HAVE_EIP712_FULL_SUPPORT #ifdef HAVE_EIP712_FULL_SUPPORT
switches[EIP712_VERBOSE_ID].initState = N_storage.verbose_eip712 ? ON_STATE : OFF_STATE; switches[EIP712_VERBOSE_ID].initState = N_storage.verbose_eip712 ? ON_STATE : OFF_STATE;
switches[EIP712_VERBOSE_ID].text = "Verbose EIP712"; switches[EIP712_VERBOSE_ID].text = "Raw messages";
switches[EIP712_VERBOSE_ID].subText = "Ignore filtering and\ndisplay raw content"; switches[EIP712_VERBOSE_ID].subText = "Displays raw content from EIP712 messages.";
switches[EIP712_VERBOSE_ID].token = EIP712_VERBOSE_TOKEN; switches[EIP712_VERBOSE_ID].token = EIP712_VERBOSE_TOKEN;
switches[EIP712_VERBOSE_ID].tuneId = TUNE_TAP_CASUAL; switches[EIP712_VERBOSE_ID].tuneId = TUNE_TAP_CASUAL;
#endif // HAVE_EIP712_FULL_SUPPORT #endif // HAVE_EIP712_FULL_SUPPORT
#ifdef HAVE_DOMAIN_NAME switches[NONCE_ID].initState = N_storage.displayNonce ? ON_STATE : OFF_STATE;
switches[DOMAIN_NAME_VERBOSE_ID].initState = switches[NONCE_ID].text = "Nonce";
N_storage.verbose_domain_name ? ON_STATE : OFF_STATE; switches[NONCE_ID].subText = "Displays nonce information in transactions.";
switches[DOMAIN_NAME_VERBOSE_ID].text = "Verbose domains"; switches[NONCE_ID].token = NONCE_TOKEN;
switches[DOMAIN_NAME_VERBOSE_ID].subText = "Show resolved address"; switches[NONCE_ID].tuneId = TUNE_TAP_CASUAL;
switches[DOMAIN_NAME_VERBOSE_ID].token = DOMAIN_NAME_VERBOSE_TOKEN;
switches[DOMAIN_NAME_VERBOSE_ID].tuneId = TUNE_TAP_CASUAL; switches[DEBUG_ID].initState = N_storage.contractDetails ? ON_STATE : OFF_STATE;
#endif // HAVE_DOMAIN_NAME switches[DEBUG_ID].text = "Debug smart contracts";
switches[DEBUG_ID].subText = "Displays contract data details.";
switches[DEBUG_ID].token = DEBUG_TOKEN;
switches[DEBUG_ID].tuneId = TUNE_TAP_CASUAL;
contents[0].type = SWITCHES_LIST; contents[0].type = SWITCHES_LIST;
contents[0].content.switchesList.nbSwitches = SETTINGS_SWITCHES_NB; contents[0].content.switchesList.nbSwitches = SETTINGS_SWITCHES_NB;

View File

@@ -2,20 +2,37 @@
#include "shared_context.h" #include "shared_context.h"
#include "ui_callbacks.h" #include "ui_callbacks.h"
#include "ui_nbgl.h" #include "ui_nbgl.h"
#include "feature_signTx.h"
static void ui_warning_contract_data_choice(bool confirm) { static void ui_warning_contract_data_choice2(bool confirm) {
if (confirm) { if (confirm) {
ui_idle(); start_signature_flow();
} else { } else {
ui_menu_settings(); report_finalize_error();
}
}
static void ui_warning_contract_data_choice1(bool confirm) {
if (confirm) {
report_finalize_error();
} else {
nbgl_useCaseChoice(
NULL,
"The transaction cannot be trusted",
"Your Ledger cannot decode this transaction. If you sign it, you could be authorizing "
"malicious actions that can drain your wallet.\n\nLearn more: ledger.com/e8",
"I accept the risk",
"Reject transaction",
ui_warning_contract_data_choice2);
} }
} }
void ui_warning_contract_data(void) { void ui_warning_contract_data(void) {
nbgl_useCaseChoice(&C_Warning_64px, nbgl_useCaseChoice(
"This message cannot\nbe clear-signed", &C_Warning_64px,
"Enable blind-signing in\nthe settings to sign\nthis transaction.", "Security risk detected",
"Exit", "It may not be safe to sign this transaction. To continue, you'll need to review the risk.",
"Go to settings", "Back to safety",
ui_warning_contract_data_choice); "Review risk",
ui_warning_contract_data_choice1);
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

View File

Before

Width:  |  Height:  |  Size: 374 B

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

View File

Before

Width:  |  Height:  |  Size: 414 B

After

Width:  |  Height:  |  Size: 414 B

View File

Before

Width:  |  Height:  |  Size: 349 B

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

Some files were not shown because too many files have changed in this diff Show More