Big Refactoring

- moved some things in header files
- now uses memory allocation functions with automatic checks, small abstraction layer
This commit is contained in:
Alexandre Paillier
2022-05-02 15:28:18 +02:00
parent 3fda010667
commit e3a8e4ccd2
2 changed files with 284 additions and 172 deletions

View File

@@ -0,0 +1,88 @@
#ifndef EIP712_H_
#define EIP712_H_
#include <stdint.h>
enum {
OFFSET_CLA = 0,
OFFSET_INS,
OFFSET_P1,
OFFSET_P2,
OFFSET_LC,
OFFSET_DATA
};
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_BYTE,
TYPE_SOL_BYTES_FIX,
TYPE_SOL_BYTES_DYN,
TYPES_COUNT
} e_type;
typedef enum
{
ARRAY_DYNAMIC = 0,
ARRAY_FIXED_SIZE
} e_array_type;
typedef enum
{
IDX_ENUM = 0,
IDX_STR_IDX,
IDX_COUNT
} t_typename_matcher_idx;
// APDUs INS
#define INS_STRUCT_DEF 0x18
#define INS_STRUCT_IMPL 0x1A
// APDUs P1
#define P1_COMPLETE 0x00
#define P1_PARTIAL 0xFF
// APDUs P2
#define P2_NAME 0x00
#define P2_ARRAY 0x0F
#define P2_FIELD 0xFF
// TypeDesc masks
#define TYPE_MASK (0xF)
#define ARRAY_MASK (1 << 7)
#define TYPESIZE_MASK (1 << 6)
#define TYPENAME_ENUM (0xF)
// Solidity typenames array mask
#define TYPENAME_MORE_TYPE (1 << 7) // For custom typename
typedef struct
{
uint16_t length;
char *str;
} t_string;
typedef struct
{
uint16_t size;
uint8_t *ptr;
} t_array;
typedef struct
{
t_string type;
t_string key;
uint8_t bytesize;
t_array array_levels;
} t_struct_field;
typedef void (*field_callback)(t_struct_field *field, uint8_t index);
#endif // EIP712_H_

View File

@@ -4,68 +4,13 @@
#include <stdbool.h>
#include <string.h>
enum {
OFFSET_CLA = 0,
OFFSET_INS,
OFFSET_P1,
OFFSET_P2,
OFFSET_LC,
OFFSET_DATA
};
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_BYTE,
TYPE_SOL_BYTES_FIX,
TYPE_SOL_BYTES_DYN,
TYPES_COUNT
} e_type;
typedef enum
{
ARRAY_DYNAMIC = 0,
ARRAY_FIXED_SIZE
} e_array_type;
#include "eip712.h"
#include "mem.h"
// APDUs INS
#define INS_STRUCT_DEF 0x18
#define INS_STRUCT_IMPL 0x1A
// APDUs P1
#define P1_COMPLETE 0x00
#define P1_PARTIAL 0xFF
// APDUs P2
#define P2_NAME 0x00
#define P2_ARRAY 0x0F
#define P2_FIELD 0xFF
// TypeDesc masks
#define TYPE_MASK (0xF)
#define ARRAY_MASK (1 << 7)
#define TYPESIZE_MASK (1 << 6)
// Solidity typename mask
#define TYPENAME_MORE_TYPE (1 << 7)
#define TYPENAME_ENUM (0xF)
#define SIZE_MEM_BUFFER 1024
uint8_t mem_buffer[SIZE_MEM_BUFFER];
uint16_t mem_idx;
uint8_t *typenames_array;
uint8_t *structs_array;
uint8_t *current_struct_fields_array;
static uint8_t *typenames_array;
static uint8_t *structs_array;
static uint8_t *current_struct_fields_array;
// lib functions
const uint8_t *get_array_in_mem(const uint8_t *ptr, uint8_t *const array_size)
@@ -80,25 +25,25 @@ static inline const uint8_t *get_string_in_mem(const uint8_t *ptr, uint8_t *cons
}
// ptr must point to the beginning of a struct field
uint8_t get_struct_field_typedesc(const uint8_t *ptr)
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)
static inline 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)
static inline 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)
static inline e_type struct_field_type(const uint8_t *ptr)
{
return (get_struct_field_typedesc(ptr) & TYPE_MASK);
}
@@ -284,31 +229,55 @@ 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 uint8_t *const name_ptr,
uint8_t name_length)
{
uint8_t structs_count;
const uint8_t *struct_ptr;
const uint8_t *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, (uint8_t*)name_ptr, strlen(name_ptr));
}
//
bool set_struct_name(uint8_t *data)
bool set_struct_name(const uint8_t *const data)
{
// increment number of structs
*structs_array += 1;
// copy length
mem_buffer[mem_idx++] = data[OFFSET_LC];
*(uint8_t*)mem_alloc(1) = data[OFFSET_LC];
// copy name
memmove(&mem_buffer[mem_idx], &data[OFFSET_DATA], data[OFFSET_LC]);
mem_idx += data[OFFSET_LC];
memmove(mem_alloc(data[OFFSET_LC]), &data[OFFSET_DATA], data[OFFSET_LC]);
// initialize number of fields
current_struct_fields_array = &mem_buffer[mem_idx];
mem_buffer[mem_idx++] = 0;
current_struct_fields_array = mem_alloc(1);
*current_struct_fields_array = 0;
return true;
}
bool set_struct_field(uint8_t *data)
bool set_struct_field(const uint8_t *const data)
{
uint8_t data_idx = OFFSET_DATA;
uint8_t type_desc, len;
@@ -318,37 +287,36 @@ bool set_struct_field(uint8_t *data)
// copy TypeDesc
type_desc = data[data_idx++];
mem_buffer[mem_idx++] = type_desc;
*(uint8_t*)mem_alloc(1) = type_desc;
// check TypeSize flag in TypeDesc
if (type_desc & TYPESIZE_MASK)
{
// copy TypeSize
mem_buffer[mem_idx++] = data[data_idx++];
*(uint8_t*)mem_alloc(1) = data[data_idx++];
}
else if ((type_desc & TYPE_MASK) == TYPE_CUSTOM)
{
len = data[data_idx++];
// copy custom struct name length
mem_buffer[mem_idx++] = len;
*(uint8_t*)mem_alloc(1) = len;
// copy name
memmove(&mem_buffer[mem_idx], &data[data_idx], len);
mem_idx += len;
memmove(mem_alloc(len), &data[data_idx], len);
data_idx += len;
}
if (type_desc & ARRAY_MASK)
{
len = data[data_idx++];
mem_buffer[mem_idx++] = len;
*(uint8_t*)mem_alloc(1) = len;
while (len-- > 0)
{
mem_buffer[mem_idx++] = data[data_idx];
*(uint8_t*)mem_alloc(1) = data[data_idx];
switch (data[data_idx++])
{
case ARRAY_DYNAMIC: // nothing to do
break;
case ARRAY_FIXED_SIZE:
mem_buffer[mem_idx++] = data[data_idx++];
*(uint8_t*)mem_alloc(1) = data[data_idx++];
break;
default:
// should not be in here :^)
@@ -359,97 +327,142 @@ bool set_struct_field(uint8_t *data)
// copy length
len = data[data_idx++];
mem_buffer[mem_idx++] = len;
*(uint8_t*)mem_alloc(1) = len;
// copy name
memmove(&mem_buffer[mem_idx], &data[data_idx], len);
mem_idx += len;
memmove(mem_alloc(len), &data[data_idx], len);
return true;
}
void dump_mem(void)
void get_struct_type_string(const uint8_t *const ptr,
const uint8_t *const struct_name,
uint8_t struct_name_length)
{
uint8_t structs_count;
const uint8_t *struct_ptr;
//
uint8_t fields_count;
const uint8_t *const struct_ptr = get_structn(ptr,
struct_name,
struct_name_length);
uint16_t *typestr_length;
char *typestr;
const uint8_t *field_ptr;
//
uint8_t fields_count;
const uint8_t *name;
uint8_t length;
uint16_t field_size;
uint8_t lvls_count;
const uint8_t *lvl_ptr;
const uint8_t *name;
uint8_t name_length;
//
uint8_t array_size;
uint8_t byte_size;
uint8_t formatted_length;
// set length
typestr_length = mem_alloc(sizeof(uint16_t));
*typestr_length = 0;
struct_ptr = get_structs_array(structs_array, &structs_count);
while (structs_count-- > 0)
// add name
typestr = memmove(mem_alloc(struct_name_length), struct_name, struct_name_length);
*typestr_length += struct_name_length;
*(char*)mem_alloc(sizeof(char)) = '(';
*typestr_length += 1;
field_ptr = get_struct_fields_array(struct_ptr, &fields_count);
for (uint8_t idx = 0; idx < fields_count; ++idx)
{
name = get_struct_name(struct_ptr, &name_length);
fwrite(name, sizeof(*name), name_length, stdout);
printf("(");
field_ptr = get_struct_fields_array(struct_ptr, &fields_count);
for (int idx = 0; idx < fields_count; ++idx)
if (idx > 0)
{
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))
*(char*)mem_alloc(sizeof(char)) = ',';
*typestr_length += 1;
}
name = get_struct_field_typename(field_ptr, &length);
memmove(mem_alloc(sizeof(char) * length), name, length);
*typestr_length += length;
if (struct_field_has_typesize(field_ptr))
{
field_size = get_struct_field_typesize(field_ptr);
switch (struct_field_type(field_ptr))
{
byte_size = get_struct_field_typesize(field_ptr);
switch(struct_field_type(field_ptr))
case TYPE_SOL_INT:
case TYPE_SOL_UINT:
field_size *= 8; // bytes -> bits
break;
case TYPE_SOL_BYTES_FIX:
break;
default:
// should not be in here :^)
break;
}
// max value = 256, 3 characters max
formatted_length = sprintf(mem_alloc(sizeof(char) * 3), "%u", field_size);
mem_dealloc(3 - formatted_length); // in case it used less
*typestr_length += formatted_length;
}
if (struct_field_is_array(field_ptr))
{
lvl_ptr = get_struct_field_array_lvls_array(field_ptr, &lvls_count);
while (lvls_count-- > 0)
{
*(char*)mem_alloc(sizeof(char)) = '[';
*typestr_length += 1;
switch (struct_field_array_depth(lvl_ptr, &array_size))
{
case TYPE_SOL_INT:
case TYPE_SOL_UINT:
// bytes -> bits
printf("%u", (byte_size * 8));
case ARRAY_DYNAMIC:
break;
case TYPE_SOL_BYTES_FIX:
printf("%u", byte_size);
case ARRAY_FIXED_SIZE:
// max value = 255, 3 characters max
formatted_length = sprintf(mem_alloc(sizeof(char) * 3), "%u", array_size);
mem_dealloc(3 - formatted_length);
*typestr_length += formatted_length;
break;
default:
// should not be in here :^)
break;
}
*(char*)mem_alloc(sizeof(char)) = ']';
*typestr_length += 1;
lvl_ptr = get_next_struct_field_array_lvl(lvl_ptr);
}
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:
break;
case ARRAY_FIXED_SIZE:
printf("%u", array_size);
break;
default:
// should not be in here :^)
break;
}
printf("]");
lvl_ptr = get_next_struct_field_array_lvl(lvl_ptr);
}
}
printf(" ");
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);
*(char*)mem_alloc(sizeof(char)) = ' ';
*typestr_length += 1;
name = get_struct_field_keyname(field_ptr, &length);
memmove(mem_alloc(sizeof(char) * length), name, length);
*typestr_length += length;
field_ptr = get_next_struct_field(field_ptr);
}
return;
*(char*)mem_alloc(sizeof(char)) = ')';
*typestr_length += 1;
// FIXME: DBG
fwrite(typestr, sizeof(char), *typestr_length, stdout);
printf("\n");
}
bool handle_apdu(uint8_t *data)
void get_type_hash(const uint8_t *const ptr,
const uint8_t *const struct_name,
uint8_t struct_name_length)
{
void *mem_loc_bak;
uint16_t str_length;
// backup the memory location
mem_loc_bak = mem_alloc(0);
// get list of structs (own + dependencies), properly ordered
// loop over each struct and generate string
str_length = 0;
get_struct_type_string(ptr, struct_name, struct_name_length);
// restore the memory location
mem_dealloc(mem_alloc(0) - mem_loc_bak);
}
bool handle_apdu(const uint8_t *const data)
{
switch (data[OFFSET_INS])
{
@@ -468,9 +481,22 @@ bool handle_apdu(uint8_t *data)
}
break;
case INS_STRUCT_IMPL:
switch (data[OFFSET_P2])
{
case P2_NAME:
get_type_hash(structs_array, &data[OFFSET_DATA], data[OFFSET_LC]);
break;
case P2_FIELD:
break;
case P2_ARRAY:
break;
default:
printf("Unknown P2 0x%x for APDU 0x%x\n", data[OFFSET_P2], data[OFFSET_INS]);
return false;
}
break;
default:
printf("Unrecognized APDU");
printf("Unrecognized APDU (0x%.02x)\n", data[OFFSET_INS]);
return false;
}
return true;
@@ -478,7 +504,7 @@ bool handle_apdu(uint8_t *data)
bool init_typenames(void)
{
char *typenames_str[] = {
const char *const typenames_str[] = {
"int",
"uint",
"address",
@@ -487,7 +513,7 @@ bool init_typenames(void)
"byte",
"bytes"
};
int enum_to_idx[][2] = {
const int enum_to_idx[][IDX_COUNT] = {
{ TYPE_SOL_INT, 0 },
{ TYPE_SOL_UINT, 1},
{ TYPE_SOL_ADDRESS, 2 },
@@ -497,42 +523,41 @@ bool init_typenames(void)
{ TYPE_SOL_BYTES_FIX, 6 },
{ TYPE_SOL_BYTES_DYN, 6 }
};
bool first_match;
uint8_t *previous_match;
uint8_t typename_len;
typenames_array = &mem_buffer[mem_idx++];
typenames_array = mem_alloc(1);
*typenames_array = 0;
// loop over typenames
for (size_t s_idx = 0;
s_idx < (sizeof(typenames_str) / sizeof(typenames_str[0]));
s_idx < (sizeof(typenames_str) / sizeof(typenames_str[IDX_ENUM]));
++s_idx)
{
first_match = true;
previous_match = NULL;
// loop over enum/typename pairs
for (size_t e_idx = 0;
e_idx < (sizeof(enum_to_idx) / sizeof(enum_to_idx[0]));
e_idx < (sizeof(enum_to_idx) / sizeof(enum_to_idx[IDX_ENUM]));
++e_idx)
{
if (s_idx == (size_t)enum_to_idx[e_idx][1]) // match
if (s_idx == (size_t)enum_to_idx[e_idx][IDX_STR_IDX]) // match
{
mem_buffer[mem_idx] = enum_to_idx[e_idx][0];
if (!first_match) // in case of a previous match, mark it
if (previous_match) // in case of a previous match, mark it
{
mem_buffer[mem_idx - 1] |= TYPENAME_MORE_TYPE;
*previous_match |= TYPENAME_MORE_TYPE;
}
mem_idx += 1;
first_match = false;
previous_match = mem_alloc(1);
*previous_match = enum_to_idx[e_idx][IDX_ENUM];
}
}
if (!first_match) // if at least one match was found
if (previous_match) // if at least one match was found
{
mem_buffer[mem_idx++] = strlen(typenames_str[s_idx]);
typename_len = strlen(typenames_str[s_idx]);
*(uint8_t*)mem_alloc(1) = typename_len;
// copy typename
memcpy(&mem_buffer[mem_idx],
memcpy(mem_alloc(typename_len),
typenames_str[s_idx],
mem_buffer[mem_idx - 1]);
// increment mem idx by typename length
mem_idx += mem_buffer[mem_idx - 1];
typename_len);
}
// increment array size
*typenames_array += 1;
@@ -543,15 +568,15 @@ bool init_typenames(void)
void init_heap(void)
{
// init global variables
mem_idx = 0;
init_mem();
init_typenames();
// set types pointer
structs_array = &mem_buffer[mem_idx];
structs_array = mem_alloc(1);
// create len(types)
mem_buffer[mem_idx++] = 0;
*structs_array = 0;
}
int main(void)
@@ -595,7 +620,6 @@ int main(void)
return EXIT_FAILURE;
}
}
dump_mem();
printf("\n%d bytes used in RAM\n", (mem_idx + 1));
//printf("\n%d bytes used in RAM\n", (mem_idx + 1));
return EXIT_SUCCESS;
}