From b782a6913712ec291bb04be9e8bb293a6822b32b Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Tue, 5 Jul 2022 11:41:46 +0200 Subject: [PATCH] Moved all typed data in RAM related code into its own file --- src_features/signMessageEIP712/eip712.h | 53 --- src_features/signMessageEIP712/entrypoint.c | 361 +------------- src_features/signMessageEIP712/field_hash.c | 1 + .../format_hash_field_type.c | 1 + src_features/signMessageEIP712/path.c | 1 + .../signMessageEIP712/sol_typenames.c | 1 + src_features/signMessageEIP712/type_hash.c | 1 + src_features/signMessageEIP712/typed_data.c | 441 ++++++++++++++++++ src_features/signMessageEIP712/typed_data.h | 69 +++ src_features/signMessageEIP712/ui_logic.c | 1 + 10 files changed, 517 insertions(+), 413 deletions(-) create mode 100644 src_features/signMessageEIP712/typed_data.c create mode 100644 src_features/signMessageEIP712/typed_data.h diff --git a/src_features/signMessageEIP712/eip712.h b/src_features/signMessageEIP712/eip712.h index ff68f5b..7561c03 100644 --- a/src_features/signMessageEIP712/eip712.h +++ b/src_features/signMessageEIP712/eip712.h @@ -6,27 +6,6 @@ #include #include -typedef enum -{ - // contract defined struct - TYPE_CUSTOM = 0, - // native types - TYPE_SOL_INT, - TYPE_SOL_UINT, - TYPE_SOL_ADDRESS, - TYPE_SOL_BOOL, - TYPE_SOL_STRING, - TYPE_SOL_BYTES_FIX, - TYPE_SOL_BYTES_DYN, - TYPES_COUNT -} e_type; - -typedef enum -{ - ARRAY_DYNAMIC = 0, - ARRAY_FIXED_SIZE -} e_array_type; - // APDUs INS #define INS_STRUCT_DEF 0x18 #define INS_STRUCT_IMPL 0x1A @@ -45,12 +24,6 @@ typedef enum #define P2_KEY 0x00 #define P2_VALUE 0xFF -// TypeDesc masks -#define TYPE_MASK (0xF) -#define ARRAY_MASK (1 << 7) -#define TYPESIZE_MASK (1 << 6) -#define TYPENAME_ENUM (0xF) - typedef enum { EIP712_TYPE_HASH, @@ -62,32 +35,6 @@ typedef enum #define DOMAIN_STRUCT_NAME "EIP712Domain" -// TODO: Move these into a new file -const char *get_struct_name(const uint8_t *ptr, uint8_t *const length); -const uint8_t *get_struct_fields_array(const uint8_t *ptr, - uint8_t *const length); -const char *get_struct_field_typename(const uint8_t *ptr, - uint8_t *const length); -bool struct_field_has_typesize(const uint8_t *ptr); -uint8_t get_struct_field_typesize(const uint8_t *ptr); -bool struct_field_is_array(const uint8_t *ptr); -e_type struct_field_type(const uint8_t *ptr); -const uint8_t *get_struct_field_array_lvls_array(const uint8_t *ptr, - uint8_t *const length); -e_array_type struct_field_array_depth(const uint8_t *ptr, - uint8_t *const array_size); -const uint8_t *get_next_struct_field_array_lvl(const uint8_t *ptr); -const char *get_struct_field_typename(const uint8_t *ptr, - uint8_t *const length); -const char *get_struct_field_keyname(const uint8_t *ptr, - uint8_t *const length); -const uint8_t *get_next_struct_field(const void *ptr); -const uint8_t *get_structn(const uint8_t *const ptr, - const char *const name_ptr, - const uint8_t name_length); -const void *get_array_in_mem(const void *ptr, uint8_t *const array_size); -const char *get_string_in_mem(const uint8_t *ptr, uint8_t *const string_length); - #endif // HAVE_EIP712_FULL_SUPPORT #endif // EIP712_H_ diff --git a/src_features/signMessageEIP712/entrypoint.c b/src_features/signMessageEIP712/entrypoint.c index 2daf964..5304391 100644 --- a/src_features/signMessageEIP712/entrypoint.c +++ b/src_features/signMessageEIP712/entrypoint.c @@ -17,6 +17,7 @@ #include "ui_logic.h" #include "common_712.h" #include "path.h" +#include "typed_data.h" #ifdef HAVE_EIP712_TESTING_KEY static const uint8_t EIP712_FEEDER_PUBLIC_KEY[] = { @@ -28,366 +29,6 @@ static const uint8_t EIP712_FEEDER_PUBLIC_KEY[] = { }; #endif // HAVE_EIP712_TESTING_KEY -// lib functions -const void *get_array_in_mem(const void *ptr, uint8_t *const array_size) -{ - *array_size = *(uint8_t*)ptr; - return (ptr + 1); -} - -const char *get_string_in_mem(const uint8_t *ptr, uint8_t *const string_length) -{ - return (char*)get_array_in_mem(ptr, string_length); -} - -// ptr must point to the beginning of a struct field -static inline uint8_t get_struct_field_typedesc(const uint8_t *ptr) -{ - return *ptr; -} - -// ptr must point to the beginning of a struct field -bool struct_field_is_array(const uint8_t *ptr) -{ - return (get_struct_field_typedesc(ptr) & ARRAY_MASK); -} - -// ptr must point to the beginning of a struct field -bool struct_field_has_typesize(const uint8_t *ptr) -{ - return (get_struct_field_typedesc(ptr) & TYPESIZE_MASK); -} - -// ptr must point to the beginning of a struct field -e_type struct_field_type(const uint8_t *ptr) -{ - return (get_struct_field_typedesc(ptr) & TYPE_MASK); -} - -// ptr must point to the beginning of a struct field -// TODO: Extra check inside or not -uint8_t get_struct_field_typesize(const uint8_t *ptr) -{ - return *(ptr + 1); -} - -// ptr must point to the beginning of a struct field -const char *get_struct_field_custom_typename(const uint8_t *ptr, - uint8_t *const length) -{ - ptr += 1; // skip TypeDesc - return get_string_in_mem(ptr, length); -} - -// ptr must point to the beginning of a struct field -const char *get_struct_field_typename(const uint8_t *ptr, - uint8_t *const length) -{ - if (struct_field_type(ptr) == TYPE_CUSTOM) - { - return get_struct_field_custom_typename(ptr, length); - } - return get_struct_field_sol_typename(ptr, length); -} - -// ptr must point to the beginning of a depth level -e_array_type struct_field_array_depth(const uint8_t *ptr, - uint8_t *const array_size) -{ - if (*ptr == ARRAY_FIXED_SIZE) - { - *array_size = *(ptr + 1); - } - return *ptr; -} - -// ptr must point to the beginning of a struct field level -const uint8_t *get_next_struct_field_array_lvl(const uint8_t *ptr) -{ - switch (*ptr) - { - case ARRAY_DYNAMIC: - break; - case ARRAY_FIXED_SIZE: - ptr += 1; - break; - default: - // should not be in here :^) - apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; - return NULL; - } - return ptr + 1; -} - -// Skips TypeDesc and TypeSize/Length+TypeName -// Came to be since it is used in multiple functions -// TODO: Find better name -const uint8_t *struct_field_half_skip(const uint8_t *ptr) -{ - const uint8_t *field_ptr; - uint8_t size; - - field_ptr = ptr; - ptr += 1; // skip TypeDesc - if (struct_field_type(field_ptr) == TYPE_CUSTOM) - { - get_string_in_mem(ptr, &size); - ptr += (1 + size); // skip typename - } - else if (struct_field_has_typesize(field_ptr)) - { - ptr += 1; // skip TypeSize - } - return ptr; -} - -// ptr must point to the beginning of a struct field -const uint8_t *get_struct_field_array_lvls_array(const uint8_t *ptr, - uint8_t *const length) -{ - ptr = struct_field_half_skip(ptr); - return get_array_in_mem(ptr, length); -} - -// ptr must point to the beginning of a struct field -const char *get_struct_field_keyname(const uint8_t *ptr, - uint8_t *const length) -{ - const uint8_t *field_ptr; - uint8_t size; - - field_ptr = ptr; - ptr = struct_field_half_skip(ptr); - if (struct_field_is_array(field_ptr)) - { - ptr = get_array_in_mem(ptr, &size); - while (size-- > 0) - { - ptr = get_next_struct_field_array_lvl(ptr); - } - } - return get_string_in_mem(ptr, length); -} - -// ptr must point to the beginning of a struct field -const uint8_t *get_next_struct_field(const void *ptr) -{ - uint8_t length; - - ptr = (uint8_t*)get_struct_field_keyname(ptr, &length); - return (ptr + length); -} - -// ptr must point to the beginning of a struct -const char *get_struct_name(const uint8_t *ptr, uint8_t *const length) -{ - return (char*)get_string_in_mem(ptr, length); -} - -// ptr must point to the beginning of a struct -const uint8_t *get_struct_fields_array(const uint8_t *ptr, - uint8_t *const length) -{ - uint8_t name_length; - - get_struct_name(ptr, &name_length); - ptr += (1 + name_length); // skip length - return get_array_in_mem(ptr, length); -} - -// ptr must point to the beginning of a struct -const uint8_t *get_next_struct(const uint8_t *ptr) -{ - uint8_t fields_count; - - ptr = get_struct_fields_array(ptr, &fields_count); - while (fields_count-- > 0) - { - ptr = get_next_struct_field(ptr); - } - return ptr; -} - -// ptr must point to the size of the structs array -const uint8_t *get_structs_array(const uint8_t *ptr, uint8_t *const length) -{ - return get_array_in_mem(ptr, length); -} - -// Finds struct with a given name -const uint8_t *get_structn(const uint8_t *const ptr, - const char *const name_ptr, - const uint8_t name_length) -{ - uint8_t structs_count; - const uint8_t *struct_ptr; - const char *name; - uint8_t length; - - struct_ptr = get_structs_array(ptr, &structs_count); - while (structs_count-- > 0) - { - name = get_struct_name(struct_ptr, &length); - if ((name_length == length) && (memcmp(name, name_ptr, length) == 0)) - { - return struct_ptr; - } - struct_ptr = get_next_struct(struct_ptr); - } - return NULL; -} - -static inline const uint8_t *get_struct(const uint8_t *const ptr, - const char *const name_ptr) -{ - return get_structn(ptr, name_ptr, strlen(name_ptr)); -} -// - -bool set_struct_name(const uint8_t *const data) -{ - uint8_t *length_ptr; - char *name_ptr; - - // increment number of structs - *(eip712_context->structs_array) += 1; - - // copy length - if ((length_ptr = mem_alloc(sizeof(uint8_t))) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - *length_ptr = data[OFFSET_LC]; - - // copy name - if ((name_ptr = mem_alloc(sizeof(char) * data[OFFSET_LC])) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - memmove(name_ptr, &data[OFFSET_CDATA], data[OFFSET_LC]); - - // initialize number of fields - if ((eip712_context->current_struct_fields_array = mem_alloc(sizeof(uint8_t))) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - *(eip712_context->current_struct_fields_array) = 0; - return true; -} - -// TODO: Split this function -// TODO: Handle partial sends -bool set_struct_field(const uint8_t *const data) -{ - uint8_t data_idx = OFFSET_CDATA; - uint8_t *type_desc_ptr; - uint8_t *type_size_ptr; - uint8_t *typename_len_ptr; - char *typename; - uint8_t *array_levels_count; - e_array_type *array_level; - uint8_t *array_level_size; - uint8_t *fieldname_len_ptr; - char *fieldname_ptr; - - // increment number of struct fields - *(eip712_context->current_struct_fields_array) += 1; - - // copy TypeDesc - if ((type_desc_ptr = mem_alloc(sizeof(uint8_t))) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - *type_desc_ptr = data[data_idx++]; - - // check TypeSize flag in TypeDesc - if (*type_desc_ptr & TYPESIZE_MASK) - { - // copy TypeSize - if ((type_size_ptr = mem_alloc(sizeof(uint8_t))) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - *type_size_ptr = data[data_idx++]; - } - else if ((*type_desc_ptr & TYPE_MASK) == TYPE_CUSTOM) - { - // copy custom struct name length - if ((typename_len_ptr = mem_alloc(sizeof(uint8_t))) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - *typename_len_ptr = data[data_idx++]; - - // copy name - if ((typename = mem_alloc(sizeof(char) * *typename_len_ptr)) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - memmove(typename, &data[data_idx], *typename_len_ptr); - data_idx += *typename_len_ptr; - } - if (*type_desc_ptr & ARRAY_MASK) - { - if ((array_levels_count = mem_alloc(sizeof(uint8_t))) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - *array_levels_count = data[data_idx++]; - for (int idx = 0; idx < *array_levels_count; ++idx) - { - if ((array_level = mem_alloc(sizeof(uint8_t))) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - *array_level = data[data_idx++]; - switch (*array_level) - { - case ARRAY_DYNAMIC: // nothing to do - break; - case ARRAY_FIXED_SIZE: - if ((array_level_size = mem_alloc(sizeof(uint8_t))) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - *array_level_size = data[data_idx++]; - break; - default: - // should not be in here :^) - apdu_response_code = APDU_RESPONSE_INVALID_DATA; - return false; - } - } - } - - // copy length - if ((fieldname_len_ptr = mem_alloc(sizeof(uint8_t))) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - *fieldname_len_ptr = data[data_idx++]; - - // copy name - if ((fieldname_ptr = mem_alloc(sizeof(char) * *fieldname_len_ptr)) == NULL) - { - apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - memmove(fieldname_ptr, &data[data_idx], *fieldname_len_ptr); - return true; -} - void handle_eip712_return_code(bool ret) { if (ret) diff --git a/src_features/signMessageEIP712/field_hash.c b/src_features/signMessageEIP712/field_hash.c index c3a4eae..8e2a50b 100644 --- a/src_features/signMessageEIP712/field_hash.c +++ b/src_features/signMessageEIP712/field_hash.c @@ -13,6 +13,7 @@ #include "context.h" // contract_addr #include "utils.h" // u64_from_BE #include "apdu_constants.h" // APDU response codes +#include "typed_data.h" static s_field_hashing *fh = NULL; diff --git a/src_features/signMessageEIP712/format_hash_field_type.c b/src_features/signMessageEIP712/format_hash_field_type.c index b8a3892..a520abf 100644 --- a/src_features/signMessageEIP712/format_hash_field_type.c +++ b/src_features/signMessageEIP712/format_hash_field_type.c @@ -6,6 +6,7 @@ #include "eip712.h" #include "hash_bytes.h" #include "apdu_constants.h" // APDU response codes +#include "typed_data.h" /** * Format & hash a struct field typesize diff --git a/src_features/signMessageEIP712/path.c b/src_features/signMessageEIP712/path.c index e630e23..20c3baf 100644 --- a/src_features/signMessageEIP712/path.c +++ b/src_features/signMessageEIP712/path.c @@ -12,6 +12,7 @@ #include "mem_utils.h" #include "ui_logic.h" #include "apdu_constants.h" // APDU response codes +#include "typed_data.h" static s_path *path_struct = NULL; diff --git a/src_features/signMessageEIP712/sol_typenames.c b/src_features/signMessageEIP712/sol_typenames.c index eff24da..6fedb06 100644 --- a/src_features/signMessageEIP712/sol_typenames.c +++ b/src_features/signMessageEIP712/sol_typenames.c @@ -8,6 +8,7 @@ #include "mem.h" #include "os_pic.h" #include "apdu_constants.h" // APDU response codes +#include "typed_data.h" // Bit indicating they are more types associated to this typename #define TYPENAME_MORE_TYPE (1 << 7) diff --git a/src_features/signMessageEIP712/type_hash.c b/src_features/signMessageEIP712/type_hash.c index a4ee85b..0de3adc 100644 --- a/src_features/signMessageEIP712/type_hash.c +++ b/src_features/signMessageEIP712/type_hash.c @@ -12,6 +12,7 @@ #include "format_hash_field_type.h" #include "hash_bytes.h" #include "apdu_constants.h" // APDU response codes +#include "typed_data.h" /** * diff --git a/src_features/signMessageEIP712/typed_data.c b/src_features/signMessageEIP712/typed_data.c new file mode 100644 index 0000000..3cd5fd0 --- /dev/null +++ b/src_features/signMessageEIP712/typed_data.c @@ -0,0 +1,441 @@ +#ifdef HAVE_EIP712_FULL_SUPPORT + +#include +#include +#include "typed_data.h" +#include "sol_typenames.h" +#include "apdu_constants.h" // APDU response codes +#include "context.h" +#include "mem.h" + +// lib functions +const void *get_array_in_mem(const void *ptr, uint8_t *const array_size) +{ + if (ptr == NULL) + { + return NULL; + } + if (array_size) + { + *array_size = *(uint8_t*)ptr; + } + return (ptr + 1); +} + +const char *get_string_in_mem(const uint8_t *ptr, uint8_t *const string_length) +{ + return (char*)get_array_in_mem(ptr, string_length); +} + +// ptr must point to the beginning of a struct field +static inline uint8_t get_struct_field_typedesc(const uint8_t *ptr) +{ + if (ptr == NULL) + { + return 0; + } + return *ptr; +} + +// ptr must point to the beginning of a struct field +bool struct_field_is_array(const uint8_t *ptr) +{ + return (get_struct_field_typedesc(ptr) & ARRAY_MASK); +} + +// ptr must point to the beginning of a struct field +bool struct_field_has_typesize(const uint8_t *ptr) +{ + return (get_struct_field_typedesc(ptr) & TYPESIZE_MASK); +} + +// ptr must point to the beginning of a struct field +e_type struct_field_type(const uint8_t *ptr) +{ + return (get_struct_field_typedesc(ptr) & TYPE_MASK); +} + +// ptr must point to the beginning of a struct field +uint8_t get_struct_field_typesize(const uint8_t *ptr) +{ + if (ptr == NULL) + { + return 0; + } + return *(ptr + 1); +} + +// ptr must point to the beginning of a struct field +const char *get_struct_field_custom_typename(const uint8_t *ptr, + uint8_t *const length) +{ + if (ptr == NULL) + { + return NULL; + } + ptr += 1; // skip TypeDesc + return get_string_in_mem(ptr, length); +} + +// ptr must point to the beginning of a struct field +const char *get_struct_field_typename(const uint8_t *ptr, + uint8_t *const length) +{ + if (ptr == NULL) + { + return NULL; + } + if (struct_field_type(ptr) == TYPE_CUSTOM) + { + return get_struct_field_custom_typename(ptr, length); + } + return get_struct_field_sol_typename(ptr, length); +} + +// ptr must point to the beginning of a depth level +e_array_type struct_field_array_depth(const uint8_t *ptr, + uint8_t *const array_size) +{ + if (ptr == NULL) + { + return 0; + } + if (*ptr == ARRAY_FIXED_SIZE) + { + *array_size = *(ptr + 1); + } + return *ptr; +} + +// ptr must point to the beginning of a struct field level +const uint8_t *get_next_struct_field_array_lvl(const uint8_t *ptr) +{ + if (ptr == NULL) + { + return NULL; + } + switch (*ptr) + { + case ARRAY_DYNAMIC: + break; + case ARRAY_FIXED_SIZE: + ptr += 1; + break; + default: + // should not be in here :^) + apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + return NULL; + } + return ptr + 1; +} + +// Skips TypeDesc and TypeSize/Length+TypeName +// Came to be since it is used in multiple functions +// TODO: Find better name +const uint8_t *struct_field_half_skip(const uint8_t *ptr) +{ + const uint8_t *field_ptr; + uint8_t size; + + if (ptr == NULL) + { + return NULL; + } + field_ptr = ptr; + ptr += 1; // skip TypeDesc + if (struct_field_type(field_ptr) == TYPE_CUSTOM) + { + get_string_in_mem(ptr, &size); + ptr += (1 + size); // skip typename + } + else if (struct_field_has_typesize(field_ptr)) + { + ptr += 1; // skip TypeSize + } + return ptr; +} + +// ptr must point to the beginning of a struct field +const uint8_t *get_struct_field_array_lvls_array(const uint8_t *ptr, + uint8_t *const length) +{ + if (ptr == NULL) + { + return NULL; + } + ptr = struct_field_half_skip(ptr); + return get_array_in_mem(ptr, length); +} + +// ptr must point to the beginning of a struct field +const char *get_struct_field_keyname(const uint8_t *ptr, + uint8_t *const length) +{ + const uint8_t *field_ptr; + uint8_t size; + + if (ptr == NULL) + { + return NULL; + } + field_ptr = ptr; + ptr = struct_field_half_skip(ptr); + if (struct_field_is_array(field_ptr)) + { + ptr = get_array_in_mem(ptr, &size); + while (size-- > 0) + { + ptr = get_next_struct_field_array_lvl(ptr); + } + } + return get_string_in_mem(ptr, length); +} + +// ptr must point to the beginning of a struct field +const uint8_t *get_next_struct_field(const void *ptr) +{ + uint8_t length; + + if (ptr == NULL) + { + return NULL; + } + ptr = (uint8_t*)get_struct_field_keyname(ptr, &length); + return (ptr + length); +} + +// ptr must point to the beginning of a struct +const char *get_struct_name(const uint8_t *ptr, uint8_t *const length) +{ + if (ptr == NULL) + { + return NULL; + } + return (char*)get_string_in_mem(ptr, length); +} + +// ptr must point to the beginning of a struct +const uint8_t *get_struct_fields_array(const uint8_t *ptr, + uint8_t *const length) +{ + uint8_t name_length; + + if (ptr == NULL) + { + return NULL; + } + get_struct_name(ptr, &name_length); + ptr += (1 + name_length); // skip length + return get_array_in_mem(ptr, length); +} + +// ptr must point to the beginning of a struct +const uint8_t *get_next_struct(const uint8_t *ptr) +{ + uint8_t fields_count; + + if (ptr == NULL) + { + return NULL; + } + ptr = get_struct_fields_array(ptr, &fields_count); + while (fields_count-- > 0) + { + ptr = get_next_struct_field(ptr); + } + return ptr; +} + +// ptr must point to the size of the structs array +const uint8_t *get_structs_array(const uint8_t *ptr, uint8_t *const length) +{ + return get_array_in_mem(ptr, length); +} + +// Finds struct with a given name +const uint8_t *get_structn(const uint8_t *const ptr, + const char *const name_ptr, + const uint8_t name_length) +{ + uint8_t structs_count; + const uint8_t *struct_ptr; + const char *name; + uint8_t length; + + if ((ptr == NULL) || (name_ptr == NULL)) + { + return NULL; + } + struct_ptr = get_structs_array(ptr, &structs_count); + while (structs_count-- > 0) + { + name = get_struct_name(struct_ptr, &length); + if ((name_length == length) && (memcmp(name, name_ptr, length) == 0)) + { + return struct_ptr; + } + struct_ptr = get_next_struct(struct_ptr); + } + return NULL; +} + +static inline const uint8_t *get_struct(const uint8_t *const ptr, + const char *const name_ptr) +{ + return get_structn(ptr, name_ptr, strlen(name_ptr)); +} +// + +bool set_struct_name(const uint8_t *const data) +{ + uint8_t *length_ptr; + char *name_ptr; + + if ((data == NULL) || (eip712_context == NULL)) + { + return false; + } + // increment number of structs + *(eip712_context->structs_array) += 1; + + // copy length + if ((length_ptr = mem_alloc(sizeof(uint8_t))) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + *length_ptr = data[OFFSET_LC]; + + // copy name + if ((name_ptr = mem_alloc(sizeof(char) * data[OFFSET_LC])) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + memmove(name_ptr, &data[OFFSET_CDATA], data[OFFSET_LC]); + + // initialize number of fields + if ((eip712_context->current_struct_fields_array = mem_alloc(sizeof(uint8_t))) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + *(eip712_context->current_struct_fields_array) = 0; + return true; +} + +// TODO: Split this function +// TODO: Handle partial sends +bool set_struct_field(const uint8_t *const data) +{ + uint8_t data_idx = OFFSET_CDATA; + uint8_t *type_desc_ptr; + uint8_t *type_size_ptr; + uint8_t *typename_len_ptr; + char *typename; + uint8_t *array_levels_count; + e_array_type *array_level; + uint8_t *array_level_size; + uint8_t *fieldname_len_ptr; + char *fieldname_ptr; + + if ((data == NULL) || (eip712_context == NULL)) + { + return false; + } + // increment number of struct fields + *(eip712_context->current_struct_fields_array) += 1; + + // copy TypeDesc + if ((type_desc_ptr = mem_alloc(sizeof(uint8_t))) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + *type_desc_ptr = data[data_idx++]; + + // check TypeSize flag in TypeDesc + if (*type_desc_ptr & TYPESIZE_MASK) + { + // copy TypeSize + if ((type_size_ptr = mem_alloc(sizeof(uint8_t))) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + *type_size_ptr = data[data_idx++]; + } + else if ((*type_desc_ptr & TYPE_MASK) == TYPE_CUSTOM) + { + // copy custom struct name length + if ((typename_len_ptr = mem_alloc(sizeof(uint8_t))) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + *typename_len_ptr = data[data_idx++]; + + // copy name + if ((typename = mem_alloc(sizeof(char) * *typename_len_ptr)) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + memmove(typename, &data[data_idx], *typename_len_ptr); + data_idx += *typename_len_ptr; + } + if (*type_desc_ptr & ARRAY_MASK) + { + if ((array_levels_count = mem_alloc(sizeof(uint8_t))) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + *array_levels_count = data[data_idx++]; + for (int idx = 0; idx < *array_levels_count; ++idx) + { + if ((array_level = mem_alloc(sizeof(uint8_t))) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + *array_level = data[data_idx++]; + switch (*array_level) + { + case ARRAY_DYNAMIC: // nothing to do + break; + case ARRAY_FIXED_SIZE: + if ((array_level_size = mem_alloc(sizeof(uint8_t))) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + *array_level_size = data[data_idx++]; + break; + default: + // should not be in here :^) + apdu_response_code = APDU_RESPONSE_INVALID_DATA; + return false; + } + } + } + + // copy length + if ((fieldname_len_ptr = mem_alloc(sizeof(uint8_t))) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + *fieldname_len_ptr = data[data_idx++]; + + // copy name + if ((fieldname_ptr = mem_alloc(sizeof(char) * *fieldname_len_ptr)) == NULL) + { + apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; + return false; + } + memmove(fieldname_ptr, &data[data_idx], *fieldname_len_ptr); + return true; +} + +#endif // HAVE_EIP712_FULL_SUPPORT diff --git a/src_features/signMessageEIP712/typed_data.h b/src_features/signMessageEIP712/typed_data.h new file mode 100644 index 0000000..f367959 --- /dev/null +++ b/src_features/signMessageEIP712/typed_data.h @@ -0,0 +1,69 @@ +#ifndef TYPED_DATA_H_ +#define TYPED_DATA_H_ + +#ifdef HAVE_EIP712_FULL_SUPPORT + +#include +#include + +// TypeDesc masks +#define TYPE_MASK (0xF) +#define ARRAY_MASK (1 << 7) +#define TYPESIZE_MASK (1 << 6) +#define TYPENAME_ENUM (0xF) + + +typedef enum +{ + ARRAY_DYNAMIC = 0, + ARRAY_FIXED_SIZE +} e_array_type; + +typedef enum +{ + // contract defined struct + TYPE_CUSTOM = 0, + // native types + TYPE_SOL_INT, + TYPE_SOL_UINT, + TYPE_SOL_ADDRESS, + TYPE_SOL_BOOL, + TYPE_SOL_STRING, + TYPE_SOL_BYTES_FIX, + TYPE_SOL_BYTES_DYN, + TYPES_COUNT +} e_type; + +const void *get_array_in_mem(const void *ptr, uint8_t *const array_size); +const char *get_string_in_mem(const uint8_t *ptr, uint8_t *const string_length); +bool struct_field_is_array(const uint8_t *ptr); +bool struct_field_has_typesize(const uint8_t *ptr); +e_type struct_field_type(const uint8_t *ptr); +uint8_t get_struct_field_typesize(const uint8_t *ptr); +const char *get_struct_field_custom_typename(const uint8_t *ptr, + uint8_t *const length); +const char *get_struct_field_typename(const uint8_t *ptr, + uint8_t *const length); +e_array_type struct_field_array_depth(const uint8_t *ptr, + uint8_t *const array_size); +const uint8_t *get_next_struct_field_array_lvl(const uint8_t *ptr); +const uint8_t *struct_field_half_skip(const uint8_t *ptr); +const uint8_t *get_struct_field_array_lvls_array(const uint8_t *ptr, + uint8_t *const length); +const char *get_struct_field_keyname(const uint8_t *ptr, + uint8_t *const length); +const uint8_t *get_next_struct_field(const void *ptr); +const char *get_struct_name(const uint8_t *ptr, uint8_t *const length); +const uint8_t *get_struct_fields_array(const uint8_t *ptr, + uint8_t *const length); +const uint8_t *get_next_struct(const uint8_t *ptr); +const uint8_t *get_structs_array(const uint8_t *ptr, uint8_t *const length); +const uint8_t *get_structn(const uint8_t *const ptr, + const char *const name_ptr, + const uint8_t name_length); +bool set_struct_name(const uint8_t *const data); +bool set_struct_field(const uint8_t *const data); + +#endif // HAVE_EIP712_FULL_SUPPORT + +#endif // TYPED_DATA_H_ diff --git a/src_features/signMessageEIP712/ui_logic.c b/src_features/signMessageEIP712/ui_logic.c index fa21891..c66bdf2 100644 --- a/src_features/signMessageEIP712/ui_logic.c +++ b/src_features/signMessageEIP712/ui_logic.c @@ -17,6 +17,7 @@ #include "uint256.h" // tostring256 && tostring256_signed #include "path.h" // path_get_root_type #include "apdu_constants.h" // APDU response codes +#include "typed_data.h" static t_ui_context *ui_ctx = NULL;