diff --git a/client/src/ledger_app_clients/ethereum/eip712/InputData.py b/client/src/ledger_app_clients/ethereum/eip712/InputData.py index 2a1278633..49c99cb9f 100644 --- a/client/src/ledger_app_clients/ethereum/eip712/InputData.py +++ b/client/src/ledger_app_clients/ethereum/eip712/InputData.py @@ -23,6 +23,7 @@ def default_handler(): autonext_handler: Callable = default_handler +is_golden_run: bool # From a string typename, extract the type and all the array depth @@ -119,7 +120,7 @@ def send_struct_def_field(typename, keyname): return (typename, type_enum, typesize, array_lvls) -def encode_integer(value: Union[str | int], typesize: int) -> bytes: +def encode_integer(value: Union[str, int], typesize: int) -> bytes: # Some are already represented as integers in the JSON, but most as strings if isinstance(value, str): value = int(value, 0) @@ -394,6 +395,12 @@ def enable_autonext(): delay = 1/3 else: delay = 1/4 + + # golden run has to be slower to make sure we take good snapshots + # and not processing/loading screens + if is_golden_run: + delay *= 3 + signal.setitimer(signal.ITIMER_REAL, delay, delay) @@ -404,10 +411,12 @@ def disable_autonext(): def process_data(aclient: EthAppClient, data_json: dict, filters: Optional[dict] = None, - autonext: Optional[Callable] = None) -> bool: + autonext: Optional[Callable] = None, + golden_run: bool = False) -> bool: global sig_ctx global app_client global autonext_handler + global is_golden_run # deepcopy because this function modifies the dict data_json = copy.deepcopy(data_json) @@ -422,6 +431,8 @@ def process_data(aclient: EthAppClient, autonext_handler = autonext signal.signal(signal.SIGALRM, next_timeout) + is_golden_run = golden_run + if filters: init_signature_context(types, domain) diff --git a/src/shared_context.h b/src/shared_context.h index 85a2296d1..dfde37f12 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -138,8 +138,12 @@ typedef struct txStringProperties_s { #ifdef TARGET_NANOS #define SHARED_CTX_FIELD_1_SIZE 100 #else +#ifdef SCREEN_SIZE_WALLET +#define SHARED_CTX_FIELD_1_SIZE 380 +#else #define SHARED_CTX_FIELD_1_SIZE 256 #endif +#endif #define SHARED_CTX_FIELD_2_SIZE 40 typedef struct strDataTmp_s { diff --git a/src_features/signMessageEIP712/field_hash.c b/src_features/signMessageEIP712/field_hash.c index a265867d1..bec2ff43d 100644 --- a/src_features/signMessageEIP712/field_hash.c +++ b/src_features/signMessageEIP712/field_hash.c @@ -61,7 +61,6 @@ static const uint8_t *field_hash_prepare(const void *const field_ptr, fh->state = FHS_WAITING_FOR_MORE; if (IS_DYN(field_type)) { CX_CHECK(cx_keccak_init_no_throw(&global_sha3, 256)); - ui_712_new_field(field_ptr, data, *data_length); } return data; end: @@ -106,11 +105,6 @@ static const uint8_t *field_hash_finalize_static(const void *const field_ptr, apdu_response_code = APDU_RESPONSE_INVALID_DATA; PRINTF("Unknown solidity type!\n"); } - - if (value == NULL) { - return NULL; - } - ui_712_new_field(field_ptr, data, data_length); return value; } @@ -245,6 +239,7 @@ static bool field_hash_finalize(const void *const field_ptr, bool field_hash(const uint8_t *data, uint8_t data_length, bool partial) { const void *field_ptr; e_type field_type; + bool first = fh->state == FHS_IDLE; if ((fh == NULL) || ((field_ptr = path_get_field()) == NULL)) { apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; @@ -252,8 +247,11 @@ bool field_hash(const uint8_t *data, uint8_t data_length, bool partial) { } field_type = struct_field_type(field_ptr); - if (fh->state == FHS_IDLE) // first packet for this frame - { + // first packet for this frame + if (first) { + if (!ui_712_show_raw_key(field_ptr)) { + return false; + } if (data_length < 2) { apdu_response_code = APDU_RESPONSE_INVALID_DATA; return false; @@ -270,6 +268,9 @@ bool field_hash(const uint8_t *data, uint8_t data_length, bool partial) { if (IS_DYN(field_type)) { hash_nbytes(data, data_length, (cx_hash_t *) &global_sha3); } + if (!ui_712_feed_to_display(field_ptr, data, data_length, first, fh->remaining_size == 0)) { + return false; + } if (fh->remaining_size == 0) { if (partial) // only makes sense if marked as complete { @@ -287,7 +288,6 @@ bool field_hash(const uint8_t *data, uint8_t data_length, bool partial) { } handle_eip712_return_code(true); } - return true; } diff --git a/src_features/signMessageEIP712/ui_logic.c b/src_features/signMessageEIP712/ui_logic.c index a81ae68d5..d70b6de50 100644 --- a/src_features/signMessageEIP712/ui_logic.c +++ b/src_features/signMessageEIP712/ui_logic.c @@ -56,6 +56,9 @@ typedef struct { uint8_t field_flags; uint8_t structs_to_review; s_amount_context amount; +#ifdef SCREEN_SIZE_WALLET + char ui_pairs_buffer[(SHARED_CTX_FIELD_1_SIZE + SHARED_CTX_FIELD_2_SIZE) * 2]; +#endif } t_ui_context; static t_ui_context *ui_ctx = NULL; @@ -89,9 +92,9 @@ static bool ui_712_field_shown(void) { * @param[in] dst_length destination buffer length * @param[in] explicit_trunc if truncation should be explicitly shown */ -static void ui_712_set_buf(const char *const src, +static void ui_712_set_buf(const char *src, size_t src_length, - char *const dst, + char *dst, size_t dst_length, bool explicit_trunc) { uint8_t cpy_length; @@ -124,7 +127,7 @@ void ui_712_finalize_field(void) { * @param[in] str the new title * @param[in] length its length */ -void ui_712_set_title(const char *const str, uint8_t length) { +void ui_712_set_title(const char *str, size_t length) { ui_712_set_buf(str, length, strings.tmp.tmp2, sizeof(strings.tmp.tmp2), false); } @@ -134,7 +137,7 @@ void ui_712_set_title(const char *const str, uint8_t length) { * @param[in] str the new value * @param[in] length its length */ -void ui_712_set_value(const char *const str, uint8_t length) { +void ui_712_set_value(const char *str, size_t length) { ui_712_set_buf(str, length, strings.tmp.tmp, sizeof(strings.tmp.tmp), true); } @@ -170,6 +173,9 @@ e_eip712_nfs ui_712_next_field(void) { } else if (!ui_ctx->end_reached) { handle_eip712_return_code(true); state = EIP712_FIELD_INCOMING; + // So that later when we append to them, we start from an empty string + explicit_bzero(strings.tmp.tmp, sizeof(strings.tmp.tmp)); + explicit_bzero(strings.tmp.tmp2, sizeof(strings.tmp.tmp2)); } } return state; @@ -180,10 +186,10 @@ e_eip712_nfs ui_712_next_field(void) { * * @param[in] struct_ptr pointer to the structure to be shown */ -void ui_712_review_struct(const void *const struct_ptr) { +void ui_712_review_struct(const void *struct_ptr) { const char *struct_name; uint8_t struct_name_length; - const char *const title = "Review struct"; + const char *title = "Review struct"; if (ui_ctx == NULL) { return; @@ -200,13 +206,14 @@ void ui_712_review_struct(const void *const struct_ptr) { * Show the hash of the message on the generic UI step */ void ui_712_message_hash(void) { - const char *const title = "Message hash"; + const char *title = "Message hash"; ui_712_set_title(title, strlen(title)); array_bytes_string(strings.tmp.tmp, sizeof(strings.tmp.tmp), tmpCtx.messageSigningContext712.messageHash, KECCAK256_HASH_BYTESIZE); + ui_ctx->end_reached = true; ui_712_redraw_generic_step(); } @@ -215,10 +222,16 @@ void ui_712_message_hash(void) { * * @param[in] data the data that needs formatting * @param[in] length its length + * @param[in] last if this is the last chunk */ -static void ui_712_format_str(const uint8_t *const data, uint8_t length) { - if (ui_712_field_shown()) { - ui_712_set_value((char *) data, length); +static void ui_712_format_str(const uint8_t *data, uint8_t length, bool last) { + size_t max_len = sizeof(strings.tmp.tmp) - 1; + size_t cur_len = strlen(strings.tmp.tmp); + + memcpy(strings.tmp.tmp + cur_len, data, MIN(max_len - cur_len, length)); + // truncated + if (last && ((max_len - cur_len) < length)) { + memcpy(strings.tmp.tmp + max_len - 3, "...", 3); } } @@ -227,20 +240,23 @@ static void ui_712_format_str(const uint8_t *const data, uint8_t length) { * * @param[in] data the data that needs formatting * @param[in] length its length + * @param[in] first if this is the first chunk * @return if the formatting was successful */ -static bool ui_712_format_addr(const uint8_t *const data, uint8_t length) { +static bool ui_712_format_addr(const uint8_t *data, uint8_t length, bool first) { + // no reason for an address to be received over multiple chunks + if (!first) { + return false; + } if (length != ADDRESS_LENGTH) { apdu_response_code = APDU_RESPONSE_INVALID_DATA; return false; } - if (ui_712_field_shown()) { - if (!getEthDisplayableAddress((uint8_t *) data, - strings.tmp.tmp, - sizeof(strings.tmp.tmp), - chainConfig->chainId)) { - THROW(APDU_RESPONSE_ERROR_NO_INFO); - } + if (!getEthDisplayableAddress((uint8_t *) data, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + chainConfig->chainId)) { + THROW(APDU_RESPONSE_ERROR_NO_INFO); } return true; } @@ -250,21 +266,25 @@ static bool ui_712_format_addr(const uint8_t *const data, uint8_t length) { * * @param[in] data the data that needs formatting * @param[in] length its length + * @param[in] first if this is the first chunk * @return if the formatting was successful */ -static bool ui_712_format_bool(const uint8_t *const data, uint8_t length) { - const char *const true_str = "true"; - const char *const false_str = "false"; +static bool ui_712_format_bool(const uint8_t *data, uint8_t length, bool first) { + size_t max_len = sizeof(strings.tmp.tmp) - 1; + const char *true_str = "true"; + const char *false_str = "false"; const char *str; + // no reason for a boolean to be received over multiple chunks + if (!first) { + return false; + } if (length != 1) { apdu_response_code = APDU_RESPONSE_INVALID_DATA; return false; } str = *data ? true_str : false_str; - if (ui_712_field_shown()) { - ui_712_set_value(str, strlen(str)); - } + memcpy(strings.tmp.tmp, str, MIN(max_len, strlen(str))); return true; } @@ -273,17 +293,29 @@ static bool ui_712_format_bool(const uint8_t *const data, uint8_t length) { * * @param[in] data the data that needs formatting * @param[in] length its length + * @param[in] first if this is the first chunk + * @param[in] last if this is the last chunk + * @return if the formatting was successful */ -static void ui_712_format_bytes(const uint8_t *const data, uint8_t length) { - if (ui_712_field_shown()) { - array_bytes_string(strings.tmp.tmp, sizeof(strings.tmp.tmp), data, length); - // +2 for the "0x" - // x2 for each byte value is represented by 2 ASCII characters - if ((2 + (length * 2)) > (sizeof(strings.tmp.tmp) - 1)) { - strings.tmp.tmp[sizeof(strings.tmp.tmp) - 1 - 3] = '\0'; - strlcat(strings.tmp.tmp, "...", sizeof(strings.tmp.tmp)); - } +static bool ui_712_format_bytes(const uint8_t *data, uint8_t length, bool first, bool last) { + size_t max_len = sizeof(strings.tmp.tmp) - 1; + size_t cur_len = strlen(strings.tmp.tmp); + + if (first) { + memcpy(strings.tmp.tmp, "0x", MIN(max_len, 2)); + cur_len += 2; + } + if (format_hex(data, + MIN((max_len - cur_len) / 2, length), + strings.tmp.tmp + cur_len, + max_len + 1 - cur_len) < 0) { + return false; } + // truncated + if (last && (((max_len - cur_len) / 2) < length)) { + memcpy(strings.tmp.tmp + max_len - 3, "...", 3); + } + return true; } /** @@ -291,63 +323,58 @@ static void ui_712_format_bytes(const uint8_t *const data, uint8_t length) { * * @param[in] data the data that needs formatting * @param[in] length its length + * @param[in] first if this is the first chunk + * @param[in] field_ptr pointer to the EIP-712 field * @return if the formatting was successful */ -static bool ui_712_format_int(const uint8_t *const data, +static bool ui_712_format_int(const uint8_t *data, uint8_t length, - const void *const field_ptr) { + bool first, + const void *field_ptr) { uint256_t value256; uint128_t value128; int32_t value32; int16_t value16; + // no reason for an integer to be received over multiple chunks + if (!first) { + return false; + } switch (get_struct_field_typesize(field_ptr) * 8) { case 256: convertUint256BE(data, length, &value256); - if (ui_712_field_shown()) { - tostring256_signed(&value256, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp)); - } + tostring256_signed(&value256, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp)); break; case 128: convertUint128BE(data, length, &value128); - if (ui_712_field_shown()) { - tostring128_signed(&value128, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp)); - } + tostring128_signed(&value128, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp)); break; case 64: convertUint64BEto128(data, length, &value128); - if (ui_712_field_shown()) { - tostring128_signed(&value128, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp)); - } + tostring128_signed(&value128, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp)); break; case 32: value32 = 0; for (int i = 0; i < length; ++i) { ((uint8_t *) &value32)[length - 1 - i] = data[i]; } - if (ui_712_field_shown()) { - snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "%d", value32); - } + snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "%d", value32); break; case 16: value16 = 0; for (int i = 0; i < length; ++i) { ((uint8_t *) &value16)[length - 1 - i] = data[i]; } - if (ui_712_field_shown()) { - snprintf(strings.tmp.tmp, - sizeof(strings.tmp.tmp), - "%d", - value16); // expanded to 32 bits - } + snprintf(strings.tmp.tmp, + sizeof(strings.tmp.tmp), + "%d", + value16); // expanded to 32 bits break; case 8: - if (ui_712_field_shown()) { - snprintf(strings.tmp.tmp, - sizeof(strings.tmp.tmp), - "%d", - ((int8_t *) data)[0]); // expanded to 32 bits - } + snprintf(strings.tmp.tmp, + sizeof(strings.tmp.tmp), + "%d", + ((int8_t *) data)[0]); // expanded to 32 bits break; default: PRINTF("Unhandled field typesize\n"); @@ -362,14 +389,19 @@ static bool ui_712_format_int(const uint8_t *const data, * * @param[in] data the data that needs formatting * @param[in] length its length + * @param[in] first if this is the first chunk + * @return if the formatting was successful */ -static void ui_712_format_uint(const uint8_t *const data, uint8_t length) { +static bool ui_712_format_uint(const uint8_t *data, uint8_t length, bool first) { uint256_t value256; - convertUint256BE(data, length, &value256); - if (ui_712_field_shown()) { - tostring256(&value256, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp)); + // no reason for an integer to be received over multiple chunks + if (!first) { + return false; } + convertUint256BE(data, length, &value256); + tostring256(&value256, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp)); + return true; } /** @@ -472,61 +504,63 @@ static bool ui_712_format_datetime(const uint8_t *data, uint8_t length) { } /** - * Used to notify of a new field to review in the current struct (key + value) + * Formats and feeds the given input data to the display buffers * * @param[in] field_ptr pointer to the new struct field * @param[in] data pointer to the field's raw value * @param[in] length field's raw value byte-length - */ -bool ui_712_new_field(const void *const field_ptr, const uint8_t *const data, uint8_t length) { - const char *key; - uint8_t key_len; - + * @param[in] first if this is the first chunk + * @param[in] last if this is the last chunk + */ +bool ui_712_feed_to_display(const void *field_ptr, + const uint8_t *data, + uint8_t length, + bool first, + bool last) { if (ui_ctx == NULL) { apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; return false; } - // Key - if ((key = get_struct_field_keyname(field_ptr, &key_len)) == NULL) { - apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + if (first && (strlen(strings.tmp.tmp) > 0)) { return false; } - - if (ui_712_field_shown() && !(ui_ctx->field_flags & UI_712_FIELD_NAME_PROVIDED)) { - ui_712_set_title(key, key_len); - } - // Value - switch (struct_field_type(field_ptr)) { - case TYPE_SOL_STRING: - ui_712_format_str(data, length); - break; - case TYPE_SOL_ADDRESS: - if (ui_712_format_addr(data, length) == false) { - return false; - } - break; - case TYPE_SOL_BOOL: - if (ui_712_format_bool(data, length) == false) { - return false; - } - break; - case TYPE_SOL_BYTES_FIX: - case TYPE_SOL_BYTES_DYN: - ui_712_format_bytes(data, length); - break; - case TYPE_SOL_INT: - if (ui_712_format_int(data, length, field_ptr) == false) { + if (ui_712_field_shown()) { + switch (struct_field_type(field_ptr)) { + case TYPE_SOL_STRING: + ui_712_format_str(data, length, last); + break; + case TYPE_SOL_ADDRESS: + if (ui_712_format_addr(data, length, first) == false) { + return false; + } + break; + case TYPE_SOL_BOOL: + if (ui_712_format_bool(data, length, first) == false) { + return false; + } + break; + case TYPE_SOL_BYTES_FIX: + case TYPE_SOL_BYTES_DYN: + if (ui_712_format_bytes(data, length, first, last) == false) { + return false; + } + break; + case TYPE_SOL_INT: + if (ui_712_format_int(data, length, first, field_ptr) == false) { + return false; + } + break; + case TYPE_SOL_UINT: + if (ui_712_format_uint(data, length, first) == false) { + return false; + } + break; + default: + PRINTF("Unhandled type\n"); return false; - } - break; - case TYPE_SOL_UINT: - ui_712_format_uint(data, length); - break; - default: - PRINTF("Unhandled type\n"); - return false; + } } if (ui_ctx->field_flags & UI_712_AMOUNT_JOIN) { @@ -549,7 +583,7 @@ bool ui_712_new_field(const void *const field_ptr, const uint8_t *const data, ui } // Check if this field is supposed to be displayed - if (ui_712_field_shown()) { + if (last && ui_712_field_shown()) { ui_712_redraw_generic_step(); } return true; @@ -564,9 +598,9 @@ void ui_712_end_sign(void) { apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; return; } - ui_ctx->end_reached = true; if (N_storage.verbose_eip712 || (ui_ctx->filtering_mode == EIP712_FILTERING_FULL)) { + ui_ctx->end_reached = true; ui_712_switch_to_sign(); } } @@ -580,6 +614,8 @@ bool ui_712_init(void) { ui_ctx->end_reached = false; ui_ctx->filtering_mode = EIP712_FILTERING_BASIC; explicit_bzero(&ui_ctx->amount, sizeof(ui_ctx->amount)); + explicit_bzero(strings.tmp.tmp, sizeof(strings.tmp.tmp)); + explicit_bzero(strings.tmp.tmp2, sizeof(strings.tmp.tmp2)); } else { apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; } @@ -726,4 +762,37 @@ void ui_712_token_join_prepare_amount(uint8_t index, const char *name, uint8_t n ui_ctx->amount.joins[index].name_length = cpy_len; } +/** + * Set UI pair key to the raw JSON key + * + * @param[in] field_ptr pointer to the field + * @return whether it was successful or not + */ +bool ui_712_show_raw_key(const void *field_ptr) { + const char *key; + uint8_t key_len; + + if ((key = get_struct_field_keyname(field_ptr, &key_len)) == NULL) { + return false; + } + + if (ui_712_field_shown() && !(ui_ctx->field_flags & UI_712_FIELD_NAME_PROVIDED)) { + ui_712_set_title(key, key_len); + } + return true; +} + +#ifdef SCREEN_SIZE_WALLET +/* + * Get UI pairs buffer + * + * @param[out] size buffer size + * @return pointer to the buffer + */ +char *get_ui_pairs_buffer(size_t *size) { + *size = sizeof(ui_ctx->ui_pairs_buffer); + return ui_ctx->ui_pairs_buffer; +} +#endif + #endif // HAVE_EIP712_FULL_SUPPORT diff --git a/src_features/signMessageEIP712/ui_logic.h b/src_features/signMessageEIP712/ui_logic.h index dd2a7e2e6..226ccf306 100644 --- a/src_features/signMessageEIP712/ui_logic.h +++ b/src_features/signMessageEIP712/ui_logic.h @@ -18,12 +18,16 @@ bool ui_712_init(void); void ui_712_deinit(void); e_eip712_nfs ui_712_next_field(void); void ui_712_review_struct(const void *const struct_ptr); -bool ui_712_new_field(const void *const field_ptr, const uint8_t *const data, uint8_t length); +bool ui_712_feed_to_display(const void *field_ptr, + const uint8_t *data, + uint8_t length, + bool first, + bool last); void ui_712_end_sign(void); unsigned int ui_712_approve(); unsigned int ui_712_reject(); -void ui_712_set_title(const char *const str, uint8_t length); -void ui_712_set_value(const char *const str, uint8_t length); +void ui_712_set_title(const char *str, size_t length); +void ui_712_set_value(const char *str, size_t length); void ui_712_message_hash(void); void ui_712_redraw_generic_step(void); void ui_712_flag_field(bool show, bool name_provided, bool token_join, bool datetime); @@ -38,6 +42,10 @@ void ui_712_notify_filter_change(void); void ui_712_token_join_prepare_addr_check(uint8_t index); void ui_712_token_join_prepare_amount(uint8_t index, const char *name, uint8_t name_length); void amount_join_set_token_received(void); +bool ui_712_show_raw_key(const void *field_ptr); +#ifdef SCREEN_SIZE_WALLET +char *get_ui_pairs_buffer(size_t *size); +#endif #endif // HAVE_EIP712_FULL_SUPPORT diff --git a/src_nbgl/ui_sign_712.c b/src_nbgl/ui_sign_712.c index ba148bbcc..10b27d35d 100644 --- a/src_nbgl/ui_sign_712.c +++ b/src_nbgl/ui_sign_712.c @@ -7,11 +7,28 @@ #include "common_712.h" #include "nbgl_use_case.h" #include "ui_message_signing.h" +#include "ledger_assert.h" -static nbgl_contentTagValue_t pair; +static nbgl_contentTagValue_t pairs[6]; static nbgl_contentTagValueList_t pairs_list; +static uint8_t pair_idx; +static size_t buf_idx; static void message_progress(bool confirm) { + char *buf; + size_t buf_size; + size_t shift_off; + + if (pairs_list.nbPairs < pair_idx) { + buf = get_ui_pairs_buffer(&buf_size); + memmove(&pairs[0], &pairs[pairs_list.nbPairs], sizeof(pairs[0])); + memmove(buf, pairs[0].item, (buf + buf_idx) - pairs[0].item); + shift_off = pairs[0].item - buf; + buf_idx -= shift_off; + pairs[0].value -= shift_off; + pairs[0].item = buf; + pair_idx = 1; + } if (confirm) { if (ui_712_next_field() == EIP712_NO_MORE_FIELD) { ui_712_switch_to_sign(); @@ -22,22 +39,40 @@ static void message_progress(bool confirm) { } static void message_update(bool confirm) { + char *buf; + size_t buf_size; + size_t buf_off; + bool flag; + + buf = get_ui_pairs_buffer(&buf_size); if (confirm) { - explicit_bzero(&pair, sizeof(pair)); - explicit_bzero(&pairs_list, sizeof(pairs_list)); - - pair.item = strings.tmp.tmp2; - pair.value = strings.tmp.tmp; - pairs_list.nbPairs = 1; - pairs_list.pairs = &pair; - pairs_list.wrapping = false; - nbgl_useCaseReviewStreamingContinue(&pairs_list, message_progress); + buf_off = strlen(strings.tmp.tmp2) + 1; + LEDGER_ASSERT((buf_idx + buf_off) < buf_size, "UI pairs buffer overflow"); + pairs[pair_idx].item = memmove(buf + buf_idx, strings.tmp.tmp2, buf_off); + buf_idx += buf_off; + buf_off = strlen(strings.tmp.tmp) + 1; + LEDGER_ASSERT((buf_idx + buf_off) < buf_size, "UI pairs buffer overflow"); + pairs[pair_idx].value = memmove(buf + buf_idx, strings.tmp.tmp, buf_off); + buf_idx += buf_off; + pair_idx += 1; + pairs_list.nbPairs = nbgl_useCaseGetNbTagValuesInPage(pair_idx, &pairs_list, 0, &flag); + if (pairs_list.nbPairs < pair_idx) { + nbgl_useCaseReviewStreamingContinue(&pairs_list, message_progress); + } else { + message_progress(true); + } } else { ui_typed_message_review_choice(false); } } void ui_712_start(void) { + explicit_bzero(&pairs, sizeof(pairs)); + explicit_bzero(&pairs_list, sizeof(pairs_list)); + pairs_list.pairs = pairs; + pair_idx = 0; + buf_idx = 0; + nbgl_useCaseReviewStreamingStart(TYPE_MESSAGE, &C_Review_64px, TEXT_REVIEW_EIP712, @@ -50,7 +85,13 @@ void ui_712_switch_to_message(void) { } void ui_712_switch_to_sign(void) { - nbgl_useCaseReviewStreamingFinish(TEXT_SIGN_EIP712, ui_typed_message_review_choice); + if (pair_idx > 0) { + pairs_list.nbPairs = pair_idx; + pair_idx = 0; + nbgl_useCaseReviewStreamingContinue(&pairs_list, message_progress); + } else { + nbgl_useCaseReviewStreamingFinish(TEXT_SIGN_EIP712, ui_typed_message_review_choice); + } } #endif // HAVE_EIP712_FULL_SUPPORT diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00001.png index f199c83b6..3e2ea5748 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00002.png index cab5e3d4c..06912ee61 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00003.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00003.png index 9ea496caf..cb969d2e0 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00003.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00004.png index 1a9cca4e9..8b981d44c 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00004.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00005.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00005.png deleted file mode 100644 index a7ee33520..000000000 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00005.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00006.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00006.png deleted file mode 100644 index cb969d2e0..000000000 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00006.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00007.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00007.png deleted file mode 100644 index 8b981d44c..000000000 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00007.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00001.png index b93749898..0acea7328 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00002.png index 263921d8f..cb969d2e0 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00003.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00003.png index 503764efc..8b981d44c 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00003.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00004.png deleted file mode 100644 index cb969d2e0..000000000 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00005.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00005.png deleted file mode 100644 index 8b981d44c..000000000 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00005.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_personal_sign_opensea/00002.png b/tests/ragger/snapshots/flex/test_personal_sign_opensea/00002.png index 9469d10b2..5ae076436 100644 Binary files a/tests/ragger/snapshots/flex/test_personal_sign_opensea/00002.png and b/tests/ragger/snapshots/flex/test_personal_sign_opensea/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_personal_sign_opensea/00003.png b/tests/ragger/snapshots/flex/test_personal_sign_opensea/00003.png index 2394aed93..8a4f7ff66 100644 Binary files a/tests/ragger/snapshots/flex/test_personal_sign_opensea/00003.png and b/tests/ragger/snapshots/flex/test_personal_sign_opensea/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_0/00002.png b/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_0/00002.png index 9f0b89f97..8861c9254 100644 Binary files a/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_0/00002.png and b/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_0/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_1/00002.png b/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_1/00002.png index 869b785ca..2a6919bd5 100644 Binary files a/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_1/00002.png and b/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_1/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_2/00002.png b/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_2/00002.png index 869b785ca..2a6919bd5 100644 Binary files a/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_2/00002.png and b/tests/ragger/snapshots/flex/test_sign_parameter_selector/step_2/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_address_substitution_verbose/00013.png b/tests/ragger/snapshots/stax/test_eip712_address_substitution_verbose/00013.png deleted file mode 100644 index 1c2d6cd43..000000000 Binary files a/tests/ragger/snapshots/stax/test_eip712_address_substitution_verbose/00013.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00001.png index 09e7b6066..4877fb0f2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00002.png index c6131c15f..33f080651 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00003.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00003.png index 2607184da..9c2fa5d78 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00003.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00004.png index 0a055353a..54aba60e5 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00004.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00005.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00005.png deleted file mode 100644 index 6797fddee..000000000 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00005.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00006.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00006.png deleted file mode 100644 index 9c2fa5d78..000000000 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00006.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00007.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00007.png deleted file mode 100644 index 54aba60e5..000000000 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00007.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00001.png index 96b35ad68..88c9c50b8 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00002.png index 6bf91491c..9c2fa5d78 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00003.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00003.png index 187512a78..54aba60e5 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00003.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00004.png deleted file mode 100644 index 9c2fa5d78..000000000 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00005.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00005.png deleted file mode 100644 index 54aba60e5..000000000 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00005.png and /dev/null differ diff --git a/tests/ragger/test_eip712.py b/tests/ragger/test_eip712.py index 91502f764..ce7b7985b 100644 --- a/tests/ragger/test_eip712.py +++ b/tests/ragger/test_eip712.py @@ -112,11 +112,13 @@ def eip712_new_common(firmware: Firmware, app_client: EthAppClient, json_data: dict, filters: Optional[dict], - verbose: bool): + verbose: bool, + golden_run: bool): assert InputData.process_data(app_client, json_data, filters, - partial(autonext, firmware, navigator, default_screenshot_path)) + partial(autonext, firmware, navigator, default_screenshot_path), + golden_run) with app_client.eip712_sign_new(BIP32_PATH): moves = [] if firmware.device.startswith("nano"): @@ -126,15 +128,13 @@ def eip712_new_common(firmware: Firmware, moves += [NavInsID.BOTH_CLICK] else: # need to skip the message hash - if not verbose and filters is None: - moves += [NavInsID.USE_CASE_REVIEW_TAP] + moves += [NavInsID.USE_CASE_REVIEW_TAP] moves += [NavInsID.USE_CASE_REVIEW_CONFIRM] if SNAPS_CONFIG is not None: navigator.navigate_and_compare(default_screenshot_path, SNAPS_CONFIG.test_name, moves, snap_start_idx=SNAPS_CONFIG.idx) - SNAPS_CONFIG.idx += 1 else: navigator.navigate(moves) return ResponseParser.signature(app_client.response().data) @@ -173,7 +173,8 @@ def test_eip712_new(firmware: Firmware, app_client, data, filters, - verbose) + verbose, + False) recovered_addr = recover_message(data, vrs) @@ -340,7 +341,8 @@ def test_eip712_advanced_filtering(firmware: Firmware, navigator: Navigator, default_screenshot_path: Path, test_name: str, - data_set: DataSet): + data_set: DataSet, + golden_run: bool): global SNAPS_CONFIG app_client = EthAppClient(backend) @@ -355,7 +357,8 @@ def test_eip712_advanced_filtering(firmware: Firmware, app_client, data_set.data, data_set.filters, - False) + False, + golden_run) # verify signature addr = recover_message(data_set.data, vrs)