diff --git a/src_features/signMessageEIP712/entrypoint.c b/src_features/signMessageEIP712/entrypoint.c index 9858363..a4cf069 100644 --- a/src_features/signMessageEIP712/entrypoint.c +++ b/src_features/signMessageEIP712/entrypoint.c @@ -51,9 +51,242 @@ typedef enum uint8_t mem_buffer[SIZE_MEM_BUFFER]; uint16_t mem_idx; +uint8_t *typename_matcher_array; +uint8_t *typenames_array; uint8_t *structs_array; uint8_t *current_struct_fields_array; +// Typename matcher masks +#define TYPENAME_MATCHER_ENUM(m) ((m >> 4) & 0xF) +#define TYPENAME_MATCHER_IDX(m) (m & 0xF) + +// lib functions + +const uint8_t *get_array_in_mem(const uint8_t *ptr, uint8_t *const array_size) +{ + *array_size = *ptr; + return (ptr + 1); +} + +static inline const uint8_t *get_string_in_mem(const uint8_t *ptr, uint8_t *const string_length) +{ + return get_array_in_mem(ptr, string_length); +} + +// ptr must point to the beginning of a struct field +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 uint8_t *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 uint8_t *get_struct_field_sol_typename(const uint8_t *ptr, + uint8_t *const length) +{ + e_type field_type; + + uint8_t matcher_count; + const uint8_t *matcher; + uint8_t matcher_idx; + uint8_t typenames_count; + const uint8_t *typename_ptr; + + field_type = struct_field_type(ptr); + matcher = get_array_in_mem(typename_matcher_array, &matcher_count); + while (matcher_count-- > 0) + { + if (TYPENAME_MATCHER_ENUM(*matcher) == field_type) + { + matcher_idx = TYPENAME_MATCHER_IDX(*matcher); + typename_ptr = get_array_in_mem(typenames_array, &typenames_count); + // if the index, somehow, can't fit in the typenames array + if ((matcher_idx + 1) > typenames_count) return NULL; + while (typenames_count-- > 0) + { + typename_ptr = get_string_in_mem(typename_ptr, length); + if (matcher_idx-- == 0) + { + return typename_ptr; + } + typename_ptr += *length; // skip this typename, get next one + } + return NULL; // Not found + } + matcher += 1; // get next one + } + return NULL; // Not found +} + +// ptr must point to the beginning of a struct field +const uint8_t *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 :^) + break; + } + 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 uint8_t *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 uint8_t *ptr) +{ + uint8_t length; + + ptr = get_struct_field_keyname(ptr, &length); + return (ptr + length); +} + +// ptr must point to the beginning of a struct +const uint8_t *get_struct_name(const uint8_t *ptr, uint8_t *const length) +{ + return 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); +} +// + + + bool set_struct_name(uint8_t *data) @@ -133,99 +366,85 @@ bool set_struct_field(uint8_t *data) return true; } + void dump_mem(void) { - uint8_t *mem = structs_array + 1; - uint8_t type_desc; + uint8_t structs_count; + const uint8_t *struct_ptr; + // uint8_t fields_count; - uint8_t array_depth; + const uint8_t *field_ptr; + // + uint8_t lvls_count; + const uint8_t *lvl_ptr; - for (int i = 0; i < *structs_array; ++i) + const uint8_t *name; + uint8_t name_length; + // + uint8_t array_size; + uint8_t byte_size; + + + struct_ptr = get_structs_array(structs_array, &structs_count); + while (structs_count-- > 0) { - fwrite(mem + 1, *mem, sizeof(*mem), stdout); + name = get_struct_name(struct_ptr, &name_length); + fwrite(name, sizeof(*name), name_length, stdout); printf("("); - mem += (1 + *mem); - fields_count = *mem; - mem += 1; - for (int y = 0; y < fields_count; ++y) + field_ptr = get_struct_fields_array(struct_ptr, &fields_count); + for (int idx = 0; idx < fields_count; ++idx) { - if (y > 0) printf(","); - type_desc = *mem; - mem += 1; - switch (type_desc & TYPE_MASK) + if (idx > 0) printf(","); + name = get_struct_field_typename(field_ptr, &name_length); + fwrite(name, sizeof(*name), name_length, stdout); + if (struct_field_has_typesize(field_ptr)) { - case TYPE_CUSTOM: - fwrite(mem + 1, *mem, sizeof(*mem), stdout); - mem += (1 + *mem); - if (type_desc & TYPESIZE_MASK) mem += 1; - break; - case TYPE_SOL_UINT: - printf("u"); - case TYPE_SOL_INT: - printf("int"); - if (type_desc & TYPESIZE_MASK) - { - printf("%d", (*mem * 8)); - mem += 1; - } - break; - case TYPE_SOL_ADDRESS: - printf("address"); - if (type_desc & TYPESIZE_MASK) mem += 1; - break; - case TYPE_SOL_BOOL: - printf("bool"); - if (type_desc & TYPESIZE_MASK) mem += 1; - break; - case TYPE_SOL_STRING: - printf("string"); - if (type_desc & TYPESIZE_MASK) mem += 1; - break; - case TYPE_SOL_BYTE: - printf("byte"); - if (type_desc & TYPESIZE_MASK) mem += 1; - break; - case TYPE_SOL_BYTES_FIX: - printf("bytes"); - if (type_desc & TYPESIZE_MASK) - { - printf("%d", *mem); - mem += 1; - } - break; - case TYPE_SOL_BYTES_DYN: - printf("bytes"); - if (type_desc & TYPESIZE_MASK) mem += 1; - break; - default: - // should not be in here :^) - break; - } - if (type_desc & ARRAY_MASK) - { - array_depth = *mem++; - while (array_depth-- > 0) + byte_size = get_struct_field_typesize(field_ptr); + switch(struct_field_type(field_ptr)) { - switch (*mem++) + case TYPE_SOL_INT: + case TYPE_SOL_UINT: + printf("%u", (byte_size * 8)); + break; + case TYPE_SOL_BYTES_FIX: + printf("%u", byte_size); + break; + default: + // should not be in here :^) + break; + } + } + if (struct_field_is_array(field_ptr)) + { + lvl_ptr = get_struct_field_array_lvls_array(field_ptr, &lvls_count); + while (lvls_count-- > 0) + { + printf("["); + switch (struct_field_array_depth(lvl_ptr, &array_size)) { case ARRAY_DYNAMIC: - printf("[]"); break; case ARRAY_FIXED_SIZE: - printf("[%u]", *mem++); + printf("%u", array_size); break; default: // should not be in here :^) break; } + printf("]"); + lvl_ptr = get_next_struct_field_array_lvl(lvl_ptr); } } printf(" "); - fwrite(mem + 1, *mem, sizeof(*mem), stdout); - mem += (1 + *mem); + name = get_struct_field_keyname(field_ptr, &name_length); + fwrite(name, sizeof(*name), name_length, stdout); + + field_ptr = get_next_struct_field(field_ptr); } printf(")\n"); + struct_ptr = get_next_struct(struct_ptr); } + return; } bool handle_apdu(uint8_t *data) @@ -255,11 +474,62 @@ bool handle_apdu(uint8_t *data) return true; } +bool init_typenames(void) +{ + char *typenames_str[] = { + "int", + "uint", + "address", + "bool", + "string", + "byte", + "bytes" + }; + // table to match type enums to indexes in the typenames string array + int enum_to_str[][2] = { + { TYPE_SOL_INT, 0 }, + { TYPE_SOL_UINT, 1}, + { TYPE_SOL_ADDRESS, 2 }, + { TYPE_SOL_BOOL, 3 }, + { TYPE_SOL_STRING, 4 }, + { TYPE_SOL_BYTE, 5 }, + { TYPE_SOL_BYTES_FIX, 6 }, + { TYPE_SOL_BYTES_DYN, 6 } + }; + + typename_matcher_array = &mem_buffer[mem_idx++]; + *typename_matcher_array = 0; + // set matchers + for (size_t i = 0; i < (sizeof(enum_to_str) / sizeof(enum_to_str[0])); ++i) + { + mem_buffer[mem_idx++] = ((enum_to_str[i][0] << 4) | (enum_to_str[i][1])); + // increment array size + *typename_matcher_array += 1; + } + + typenames_array = &mem_buffer[mem_idx++]; + *typenames_array = 0; + // set typenames + for (size_t i = 0; i < (sizeof(typenames_str) / sizeof(typenames_str[0])); ++i) + { + mem_buffer[mem_idx++] = strlen(typenames_str[i]); // length + // copy typename + memcpy(&mem_buffer[mem_idx], typenames_str[i], mem_buffer[mem_idx - 1]); + // increment mem idx by typename length + mem_idx += mem_buffer[mem_idx - 1]; + // increment array size + *typenames_array += 1; + } + return true; +} + void init_heap(void) { // init global variables mem_idx = 0; + init_typenames(); + // set types pointer structs_array = &mem_buffer[mem_idx];