diff --git a/Makefile b/Makefile index d2c0b32..872bc15 100644 --- a/Makefile +++ b/Makefile @@ -140,7 +140,6 @@ endif # EIP-712 ifneq ($(TARGET_NAME),TARGET_NANOS) DEFINES += HAVE_EIP712_FULL_SUPPORT -#DEFINES += HAVE_EIP712_HALF_BLIND # temporary endif # Enabling debug PRINTF diff --git a/src_features/signMessageEIP712/eip712.h b/src_features/signMessageEIP712/eip712.h index d0b6964..ff68f5b 100644 --- a/src_features/signMessageEIP712/eip712.h +++ b/src_features/signMessageEIP712/eip712.h @@ -61,7 +61,6 @@ typedef enum #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define DOMAIN_STRUCT_NAME "EIP712Domain" -#define DOMAIN_STRUCT_NAME_LENGTH 12 // TODO: Move these into a new file const char *get_struct_name(const uint8_t *ptr, uint8_t *const length); diff --git a/src_features/signMessageEIP712/entrypoint.c b/src_features/signMessageEIP712/entrypoint.c index 4fa4919..754484c 100644 --- a/src_features/signMessageEIP712/entrypoint.c +++ b/src_features/signMessageEIP712/entrypoint.c @@ -409,21 +409,39 @@ bool handle_eip712_struct_def(const uint8_t *const apdu_buf) bool handle_eip712_struct_impl(const uint8_t *const apdu_buf) { bool ret = true; + bool reply_apdu = true; switch (apdu_buf[OFFSET_P2]) { case P2_NAME: // set root type - ret = path_set_root((char*)&apdu_buf[OFFSET_CDATA], - apdu_buf[OFFSET_LC]); + if (path_set_root((char*)&apdu_buf[OFFSET_CDATA], + apdu_buf[OFFSET_LC])) + { + ui_712_field_flags_reset(); + } + else + { + ret = false; + } break; case P2_FIELD: - ret = field_hash(&apdu_buf[OFFSET_CDATA], - apdu_buf[OFFSET_LC], - apdu_buf[OFFSET_P1] != P1_COMPLETE); + if (field_hash(&apdu_buf[OFFSET_CDATA], + apdu_buf[OFFSET_LC], + apdu_buf[OFFSET_P1] != P1_COMPLETE)) + { + reply_apdu = false; + } + else + { + ret = false; + } break; case P2_ARRAY: - ret = path_new_array_depth(apdu_buf[OFFSET_CDATA]); + if (!path_new_array_depth(apdu_buf[OFFSET_CDATA])) + { + ret = false; + } break; default: PRINTF("Unknown P2 0x%x for APDU 0x%x\n", @@ -431,11 +449,18 @@ bool handle_eip712_struct_impl(const uint8_t *const apdu_buf) apdu_buf[OFFSET_INS]); ret = false; } - if (!ret) + if (reply_apdu) { - // Send back the response, do not restart the event loop - G_io_apdu_buffer[0] = 0x6A; - G_io_apdu_buffer[1] = 0x80; + if (ret) + { + G_io_apdu_buffer[0] = 0x90; + G_io_apdu_buffer[1] = 0x00; + } + else + { + G_io_apdu_buffer[0] = 0x6a; + G_io_apdu_buffer[1] = 0x80; + } io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); } return ret; @@ -665,10 +690,10 @@ bool handle_eip712_filtering(const uint8_t *const apdu_buf) switch (apdu_buf[OFFSET_P1]) { case P1_ACTIVATE: - ui_ctx->filtering_mode = EIP712_FILTERING_FULL; + ui_712_set_filtering_mode(EIP712_FILTERING_FULL); break; case P1_CONTRACT_NAME: - if (ui_ctx->filtering_mode == EIP712_FILTERING_FULL) + if (ui_712_get_filtering_mode() == EIP712_FILTERING_FULL) { ret = provide_contract_name(&apdu_buf[OFFSET_CDATA], apdu_buf[OFFSET_LC]); @@ -679,7 +704,7 @@ bool handle_eip712_filtering(const uint8_t *const apdu_buf) } break; case P1_FIELD_NAME: - if (ui_ctx->filtering_mode == EIP712_FILTERING_FULL) + if (ui_712_get_filtering_mode() == EIP712_FILTERING_FULL) { ret = provide_field_name(&apdu_buf[OFFSET_CDATA], apdu_buf[OFFSET_LC]); @@ -720,9 +745,10 @@ bool handle_eip712_sign(const uint8_t *const apdu_buf) { return false; } -#ifdef HAVE_EIP712_HALF_BLIND - ui_712_message_hash(); -#endif // HAVE_EIP712_HALF_BLIND + if (ui_712_get_filtering_mode() == EIP712_FILTERING_BASIC) + { + ui_712_message_hash(); + } ui_712_end_sign(); return true; } diff --git a/src_features/signMessageEIP712/field_hash.c b/src_features/signMessageEIP712/field_hash.c index 19e9d5b..01abe08 100644 --- a/src_features/signMessageEIP712/field_hash.c +++ b/src_features/signMessageEIP712/field_hash.c @@ -67,17 +67,7 @@ bool field_hash(const uint8_t *data, if (IS_DYN(field_type)) { cx_keccak_init(&global_sha3, 256); // init hash -#ifdef HAVE_EIP712_HALF_BLIND - if (path_get_root_type() == ROOT_DOMAIN) - { - if ((keylen == 4) && (strncmp(key, "name", keylen) == 0)) - { -#endif // HAVE_EIP712_HALF_BLIND ui_712_new_field(field_ptr, data, data_length); -#ifdef HAVE_EIP712_HALF_BLIND - } - } -#endif // HAVE_EIP712_HALF_BLIND } } fh->remaining_size -= data_length; @@ -136,17 +126,7 @@ bool field_hash(const uint8_t *data, { return false; } -#ifdef HAVE_EIP712_HALF_BLIND - if (path_get_root_type() == ROOT_DOMAIN) - { - if ((keylen == 4) && (strncmp(key, "name", keylen) == 0)) - { -#endif // HAVE_EIP712_HALF_BLIND ui_712_new_field(field_ptr, data, data_length); -#ifdef HAVE_EIP712_HALF_BLIND - } - } -#endif // HAVE_EIP712_HALF_BLIND } else { @@ -193,16 +173,7 @@ bool field_hash(const uint8_t *data, } path_advance(); fh->state = FHS_IDLE; -#ifdef HAVE_EIP712_HALF_BLIND - if ((path_get_root_type() == ROOT_MESSAGE) || - ((keylen != 4) || (strncmp(key, "name", keylen) != 0))) - { - G_io_apdu_buffer[0] = 0x90; - G_io_apdu_buffer[1] = 0x00; - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); - } -#endif // HAVE_EIP712_HALF_BLIND - + ui_712_finalize_field(); } else { diff --git a/src_features/signMessageEIP712/path.c b/src_features/signMessageEIP712/path.c index e69706e..609d6a7 100644 --- a/src_features/signMessageEIP712/path.c +++ b/src_features/signMessageEIP712/path.c @@ -10,7 +10,6 @@ #include "shared_context.h" #include "ethUtils.h" #include "mem_utils.h" -#include "ui_logic.h" static s_path *path_struct = NULL; @@ -370,8 +369,8 @@ bool path_set_root(const char *const struct_name, uint8_t name_length) // init array levels at 0 path_struct->array_depth_count = 0; - if ((name_length == DOMAIN_STRUCT_NAME_LENGTH) && - (strncmp(struct_name, DOMAIN_STRUCT_NAME, DOMAIN_STRUCT_NAME_LENGTH) == 0)) + if ((name_length == strlen(DOMAIN_STRUCT_NAME)) && + (strncmp(struct_name, DOMAIN_STRUCT_NAME, name_length) == 0)) { path_struct->root_type = ROOT_DOMAIN; } @@ -382,22 +381,6 @@ bool path_set_root(const char *const struct_name, uint8_t name_length) // because the first field could be a struct type path_update(); -#ifdef HAVE_EIP712_HALF_BLIND - // Only show field for the domain - if (path_get_root_type() == ROOT_MESSAGE) - { - G_io_apdu_buffer[0] = 0x90; - G_io_apdu_buffer[1] = 0x00; - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); - } - else - { -#endif // HAVE_EIP712_HALF_BLIND - ui_712_new_root_struct(path_struct->root_struct); -#ifdef HAVE_EIP712_HALF_BLIND - } -#endif // HAVE_EIP712_HALF_BLIND - ui_712_field_flags_reset(); return true; } @@ -610,7 +593,6 @@ bool path_advance(void) } while (end_reached); path_update(); - ui_712_field_flags_reset(); return true; } @@ -623,6 +605,15 @@ e_root_type path_get_root_type(void) return path_struct->root_type; } +const void *path_get_root(void) +{ + if (path_struct == NULL) + { + return NULL; + } + return path_struct->root_struct; +} + /** * Allocates the path indexes in memory and sets it with a depth of 0. * diff --git a/src_features/signMessageEIP712/path.h b/src_features/signMessageEIP712/path.h index e5a05c1..ec8413f 100644 --- a/src_features/signMessageEIP712/path.h +++ b/src_features/signMessageEIP712/path.h @@ -38,6 +38,7 @@ bool path_init(void); void path_deinit(void); bool path_new_array_depth(uint8_t size); e_root_type path_get_root_type(void); +const void *path_get_root(void); #endif // HAVE_EIP712_FULL_SUPPORT diff --git a/src_features/signMessageEIP712/ui_logic.c b/src_features/signMessageEIP712/ui_logic.c index daab375..1edda19 100644 --- a/src_features/signMessageEIP712/ui_logic.c +++ b/src_features/signMessageEIP712/ui_logic.c @@ -15,11 +15,38 @@ #include "common_712.h" #include "context.h" // eip712_context_deinit #include "uint256.h" // tostring256 && tostring256_signed +#include "path.h" // path_get_root_type -t_ui_context *ui_ctx = NULL; +static t_ui_context *ui_ctx = NULL; +/** + * Checks on the UI context to determine if the next EIP 712 field should be shown + * + * @return whether the next field should be shown + */ +static bool ui_712_field_shown(void) +{ + bool ret = false; + + if (ui_ctx->filtering_mode == EIP712_FILTERING_BASIC) + { + if (path_get_root_type() == ROOT_DOMAIN) + { + ret = true; + } + } + else // EIP712_FILTERING_FULL + { + if (ui_ctx->field_flags & UI_712_FIELD_SHOWN) + { + ret = true; + } + } + return ret; +} + static void ui_712_set_buf(const char *const src, size_t src_length, char *const dst, @@ -44,6 +71,17 @@ static void ui_712_set_buf(const char *const src, } } +void ui_712_finalize_field(void) +{ + if (!ui_712_field_shown()) + { + G_io_apdu_buffer[0] = 0x90; + G_io_apdu_buffer[1] = 0x00; + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); + } + ui_712_field_flags_reset(); +} + /** * Set a new title for the EIP-712 generic UX_STEP * @@ -68,12 +106,20 @@ void ui_712_set_value(const char *const str, uint8_t length) void ui_712_redraw_generic_step(void) { - // not pretty, manually changes the internal state of the UX flow - // so that we always land on the first screen of a paging step without any visible - // screen glitching (quick screen switching) - G_ux.flow_stack[G_ux.stack_count - 1].index = 0; - // since the flow now thinks we are displaying the first step, do next - ux_flow_next(); + if (!ui_ctx->shown) // Initialize if it is not already + { + ux_flow_init(0, ux_712_flow, NULL); + ui_ctx->shown = true; + } + else + { + // not pretty, manually changes the internal state of the UX flow + // so that we always land on the first screen of a paging step without any visible + // screen glitching (quick screen switching) + G_ux.flow_stack[G_ux.stack_count - 1].index = 0; + // since the flow now thinks we are displaying the first step, do next + ux_flow_next(); + } } /** @@ -109,11 +155,11 @@ void ui_712_next_field(void) } /** - * Used to notify of a new struct to review (domain or message) + * Used to notify of a new struct to review * * @param[in] struct_ptr pointer to the structure */ -void ui_712_new_root_struct(const void *const struct_ptr) +void ui_712_new_struct(const void *const struct_ptr) { const char *struct_name; uint8_t struct_name_length; @@ -123,23 +169,15 @@ void ui_712_new_root_struct(const void *const struct_ptr) { return; } + ui_712_set_title(title, strlen(title)); if ((struct_name = get_struct_name(struct_ptr, &struct_name_length)) != NULL) { ui_712_set_value(struct_name, struct_name_length); } - if (!ui_ctx->shown) - { - ux_flow_init(0, ux_712_flow, NULL); - ui_ctx->shown = true; - } - else - { - ux_flow_prev(); - } + ui_712_redraw_generic_step(); } -#ifdef HAVE_EIP712_HALF_BLIND void ui_712_message_hash(void) { const char *const title = "Message hash"; @@ -150,10 +188,8 @@ void ui_712_message_hash(void) "0x%.*H", KECCAK256_HASH_BYTESIZE, tmpCtx.messageSigningContext712.messageHash); - G_ux.flow_stack[G_ux.stack_count - 1].index = 0; - ux_flow_next(); + ui_712_redraw_generic_step(); } -#endif // HAVE_EIP712_HALF_BLIND /** * Used to notify of a new field to review in the current struct (key + value) @@ -176,6 +212,12 @@ void ui_712_new_field(const void *const field_ptr, const uint8_t *const data, return; } + // Check if this field is supposed to be displayed + if (!ui_712_field_shown()) + { + return; + } + // Key if ((key = get_struct_field_keyname(field_ptr, &key_len)) != NULL) { @@ -293,9 +335,10 @@ void ui_712_end_sign(void) } ui_ctx->end_reached = true; -#ifndef HAVE_EIP712_HALF_BLIND - ui_712_next_field(); -#endif // HAVE_EIP712_HALF_BLIND + if (ui_ctx->filtering_mode == EIP712_FILTERING_FULL) + { + ui_712_next_field(); + } } /** @@ -359,6 +402,16 @@ void ui_712_flag_field(bool show, bool name_provided) } } +void ui_712_set_filtering_mode(e_eip712_filtering_mode mode) +{ + ui_ctx->filtering_mode = mode; +} + +e_eip712_filtering_mode ui_712_get_filtering_mode(void) +{ + return ui_ctx->filtering_mode; +} + void ui_712_field_flags_reset(void) { ui_ctx->field_flags = 0; diff --git a/src_features/signMessageEIP712/ui_logic.h b/src_features/signMessageEIP712/ui_logic.h index 966d81b..277932d 100644 --- a/src_features/signMessageEIP712/ui_logic.h +++ b/src_features/signMessageEIP712/ui_logic.h @@ -30,24 +30,23 @@ typedef struct uint8_t field_flags; } t_ui_context; -extern t_ui_context *ui_ctx; - bool ui_712_init(void); void ui_712_deinit(void); void ui_712_next_field(void); -void ui_712_new_root_struct(const void *const struct_ptr); +void ui_712_new_struct(const void *const struct_ptr); void ui_712_new_field(const void *const field_ptr, const uint8_t *const data, uint8_t length); void ui_712_end_sign(void); unsigned int ui_712_approve(const bagl_element_t *e); unsigned int ui_712_reject(const bagl_element_t *e); void ui_712_set_title(const char *const str, uint8_t length); void ui_712_set_value(const char *const str, uint8_t length); -#ifdef HAVE_EIP712_HALF_BLIND void ui_712_message_hash(void); -#endif // HAVE_EIP712_HALF_BLIND void ui_712_redraw_generic_step(void); void ui_712_flag_field(bool show, bool name_provided); void ui_712_field_flags_reset(void); +void ui_712_finalize_field(void); +void ui_712_set_filtering_mode(e_eip712_filtering_mode mode); +e_eip712_filtering_mode ui_712_get_filtering_mode(void); #endif // HAVE_EIP712_FULL_SUPPORT