Refactored some type EIP712 formatting and hashing code to re-use it
This commit is contained in:
116
src_features/signMessageEIP712/format_hash_field_type.c
Normal file
116
src_features/signMessageEIP712/format_hash_field_type.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#include "format_hash_field_type.h"
|
||||
#include "mem.h"
|
||||
#include "mem_utils.h"
|
||||
#include "eip712.h"
|
||||
#include "hash_bytes.h"
|
||||
|
||||
/**
|
||||
* Format & hash a struct field typesize
|
||||
*
|
||||
* @param[in] field_ptr pointer to the struct field
|
||||
* @param[in] hash_ctx pointer to the hashing context
|
||||
* @return whether the formatting & hashing were successful or not
|
||||
*/
|
||||
static bool format_hash_field_type_size(const void *const field_ptr, cx_hash_t *hash_ctx)
|
||||
{
|
||||
uint16_t field_size;
|
||||
char *uint_str_ptr;
|
||||
uint8_t uint_str_len;
|
||||
|
||||
field_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 :^)
|
||||
return false;
|
||||
}
|
||||
uint_str_ptr = mem_alloc_and_format_uint(field_size, &uint_str_len);
|
||||
hash_nbytes((uint8_t*)uint_str_ptr, uint_str_len, hash_ctx);
|
||||
mem_dealloc(uint_str_len);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format & hash a struct field array levels
|
||||
*
|
||||
* @param[in] field_ptr pointer to the struct field
|
||||
* @param[in] hash_ctx pointer to the hashing context
|
||||
* @return whether the formatting & hashing were successful or not
|
||||
*/
|
||||
static bool format_hash_field_type_array_levels(const void *const field_ptr, cx_hash_t *hash_ctx)
|
||||
{
|
||||
uint8_t array_size;
|
||||
char *uint_str_ptr;
|
||||
uint8_t uint_str_len;
|
||||
const void *lvl_ptr;
|
||||
uint8_t lvls_count;
|
||||
|
||||
lvl_ptr = get_struct_field_array_lvls_array(field_ptr, &lvls_count);
|
||||
while (lvls_count-- > 0)
|
||||
{
|
||||
hash_byte('[', hash_ctx);
|
||||
|
||||
switch (struct_field_array_depth(lvl_ptr, &array_size))
|
||||
{
|
||||
case ARRAY_DYNAMIC:
|
||||
break;
|
||||
case ARRAY_FIXED_SIZE:
|
||||
uint_str_ptr = mem_alloc_and_format_uint(array_size, &uint_str_len);
|
||||
hash_nbytes((uint8_t*)uint_str_ptr, uint_str_len, hash_ctx);
|
||||
mem_dealloc(uint_str_len);
|
||||
break;
|
||||
default:
|
||||
// should not be in here :^)
|
||||
return false;
|
||||
}
|
||||
hash_byte(']', hash_ctx);
|
||||
lvl_ptr = get_next_struct_field_array_lvl(lvl_ptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format & hash a struct field type
|
||||
*
|
||||
* @param[in] field_ptr pointer to the struct field
|
||||
* @param[in] hash_ctx pointer to the hashing context
|
||||
* @return whether the formatting & hashing were successful or not
|
||||
*/
|
||||
bool format_hash_field_type(const void *const field_ptr, cx_hash_t *hash_ctx)
|
||||
{
|
||||
const char *name;
|
||||
uint8_t length;
|
||||
|
||||
// field type name
|
||||
name = get_struct_field_typename(field_ptr, &length);
|
||||
hash_nbytes((uint8_t*)name, length, hash_ctx);
|
||||
|
||||
// field type size
|
||||
if (struct_field_has_typesize(field_ptr))
|
||||
{
|
||||
if (!format_hash_field_type_size(field_ptr, hash_ctx))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// field type array levels
|
||||
if (struct_field_is_array(field_ptr))
|
||||
{
|
||||
if (!format_hash_field_type_array_levels(field_ptr, hash_ctx))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
12
src_features/signMessageEIP712/format_hash_field_type.h
Normal file
12
src_features/signMessageEIP712/format_hash_field_type.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef FORMAT_HASH_FIELD_TYPE_H_
|
||||
#define FORMAT_HASH_FIELD_TYPE_H_
|
||||
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#include "cx.h"
|
||||
|
||||
bool format_hash_field_type(const void *const field_ptr, cx_hash_t *hash_ctx);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // FORMAT_HASH_FIELD_TYPE_H_
|
||||
33
src_features/signMessageEIP712/hash_bytes.c
Normal file
33
src_features/signMessageEIP712/hash_bytes.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#include "hash_bytes.h"
|
||||
|
||||
/**
|
||||
* Continue given progressive hash on given bytes
|
||||
*
|
||||
* @param[in] bytes_ptr pointer to bytes
|
||||
* @param[in] n number of bytes to hash
|
||||
* @param[in] hash_ctx pointer to the hashing context
|
||||
*/
|
||||
void hash_nbytes(const uint8_t *const bytes_ptr, uint8_t n, cx_hash_t *hash_ctx)
|
||||
{
|
||||
cx_hash(hash_ctx,
|
||||
0,
|
||||
bytes_ptr,
|
||||
n,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue given progressive hash on given byte
|
||||
*
|
||||
* @param[in] byte byte to hash
|
||||
* @param[in] hash_ctx pointer to the hashing context
|
||||
*/
|
||||
void hash_byte(uint8_t byte, cx_hash_t *hash_ctx)
|
||||
{
|
||||
hash_nbytes(&byte, 1, hash_ctx);
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
13
src_features/signMessageEIP712/hash_bytes.h
Normal file
13
src_features/signMessageEIP712/hash_bytes.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef HASH_BYTES_H_
|
||||
#define HASH_BYTES_H_
|
||||
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#include "cx.h"
|
||||
|
||||
void hash_nbytes(const uint8_t *const bytes_ptr, uint8_t n, cx_hash_t *hash_ctx);
|
||||
void hash_byte(uint8_t byte, cx_hash_t *hash_ctx);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // HASH_BYTES_H_
|
||||
@@ -46,8 +46,7 @@ char *mem_alloc_and_format_uint(uint32_t value, uint8_t *const length)
|
||||
// +1 for the null character
|
||||
if ((mem_ptr = mem_alloc(sizeof(char) * (size + 1))))
|
||||
{
|
||||
// should be using %u, but not supported by toolchain
|
||||
snprintf(mem_ptr, (size + 1), "%d", value);
|
||||
snprintf(mem_ptr, (size + 1), "%u", value);
|
||||
mem_dealloc(sizeof(char)); // to skip the null character
|
||||
if (length != NULL)
|
||||
{
|
||||
|
||||
@@ -9,115 +9,29 @@
|
||||
#include "type_hash.h"
|
||||
#include "shared_context.h"
|
||||
#include "ethUtils.h" // KECCAK256_HASH_BYTESIZE
|
||||
|
||||
static inline void hash_nbytes(const uint8_t *b, uint8_t n)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
PRINTF("%c", b[i]);
|
||||
}
|
||||
#endif
|
||||
cx_hash((cx_hash_t*)&global_sha3,
|
||||
0,
|
||||
b,
|
||||
n,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
static inline void hash_byte(uint8_t b)
|
||||
{
|
||||
hash_nbytes(&b, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param[in] lvl_ptr pointer to the first array level of a struct field
|
||||
* @param[in] lvls_count the number of array levels the struct field contains
|
||||
* @return \ref true it finished correctly, \ref false if it didn't (memory allocation)
|
||||
*/
|
||||
static bool format_field_type_array_levels_string(const void *lvl_ptr, uint8_t lvls_count)
|
||||
{
|
||||
uint8_t array_size;
|
||||
char *uint_str_ptr;
|
||||
uint8_t uint_str_len;
|
||||
|
||||
while (lvls_count-- > 0)
|
||||
{
|
||||
hash_byte('[');
|
||||
|
||||
switch (struct_field_array_depth(lvl_ptr, &array_size))
|
||||
{
|
||||
case ARRAY_DYNAMIC:
|
||||
break;
|
||||
case ARRAY_FIXED_SIZE:
|
||||
uint_str_ptr = mem_alloc_and_format_uint(array_size, &uint_str_len);
|
||||
hash_nbytes((uint8_t*)uint_str_ptr, uint_str_len);
|
||||
mem_dealloc(uint_str_len);
|
||||
break;
|
||||
default:
|
||||
// should not be in here :^)
|
||||
break;
|
||||
}
|
||||
hash_byte(']');
|
||||
lvl_ptr = get_next_struct_field_array_lvl(lvl_ptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#include "format_hash_field_type.h"
|
||||
#include "hash_bytes.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* @param[in] field_ptr pointer to the struct field
|
||||
* @return \ref true it finished correctly, \ref false if it didn't (memory allocation)
|
||||
*/
|
||||
static bool encode_and_hash_field(const void *field_ptr)
|
||||
static bool encode_and_hash_field(const void *const field_ptr)
|
||||
{
|
||||
const char *name;
|
||||
uint8_t length;
|
||||
uint16_t field_size;
|
||||
uint8_t lvls_count;
|
||||
const uint8_t *lvl_ptr;
|
||||
char *uint_str_ptr;
|
||||
uint8_t uint_str_len;
|
||||
|
||||
// field type name
|
||||
name = get_struct_field_typename(field_ptr, &length);
|
||||
hash_nbytes((uint8_t*)name, length);
|
||||
|
||||
// field type size
|
||||
if (struct_field_has_typesize(field_ptr))
|
||||
if (!format_hash_field_type(field_ptr, (cx_hash_t*)&global_sha3))
|
||||
{
|
||||
field_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;
|
||||
}
|
||||
uint_str_ptr = mem_alloc_and_format_uint(field_size, &uint_str_len);
|
||||
hash_nbytes((uint8_t*)uint_str_ptr, uint_str_len);
|
||||
mem_dealloc(uint_str_len);
|
||||
}
|
||||
|
||||
// field type array levels
|
||||
if (struct_field_is_array(field_ptr))
|
||||
{
|
||||
lvl_ptr = get_struct_field_array_lvls_array(field_ptr, &lvls_count);
|
||||
format_field_type_array_levels_string(lvl_ptr, lvls_count);
|
||||
return false;
|
||||
}
|
||||
// space between field type name and field name
|
||||
hash_byte(' ');
|
||||
hash_byte(' ', (cx_hash_t*)&global_sha3);
|
||||
|
||||
// field name
|
||||
name = get_struct_field_keyname(field_ptr, &length);
|
||||
hash_nbytes((uint8_t*)name, length);
|
||||
hash_nbytes((uint8_t*)name, length, (cx_hash_t*)&global_sha3);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -127,7 +41,7 @@ static bool encode_and_hash_field(const void *field_ptr)
|
||||
* @param[in] str_length length of the formatted string in memory
|
||||
* @return pointer of the string in memory, \ref NULL in case of an error
|
||||
*/
|
||||
static bool encode_and_hash_type(const uint8_t *const struct_ptr)
|
||||
static bool encode_and_hash_type(const void *const struct_ptr)
|
||||
{
|
||||
const char *struct_name;
|
||||
uint8_t struct_name_length;
|
||||
@@ -136,10 +50,10 @@ static bool encode_and_hash_type(const uint8_t *const struct_ptr)
|
||||
|
||||
// struct name
|
||||
struct_name = get_struct_name(struct_ptr, &struct_name_length);
|
||||
hash_nbytes((uint8_t*)struct_name, struct_name_length);
|
||||
hash_nbytes((uint8_t*)struct_name, struct_name_length, (cx_hash_t*)&global_sha3);
|
||||
|
||||
// opening struct parenthese
|
||||
hash_byte('(');
|
||||
hash_byte('(', (cx_hash_t*)&global_sha3);
|
||||
|
||||
field_ptr = get_struct_fields_array(struct_ptr, &fields_count);
|
||||
for (uint8_t idx = 0; idx < fields_count; ++idx)
|
||||
@@ -147,7 +61,7 @@ static bool encode_and_hash_type(const uint8_t *const struct_ptr)
|
||||
// comma separating struct fields
|
||||
if (idx > 0)
|
||||
{
|
||||
hash_byte(',');
|
||||
hash_byte(',', (cx_hash_t*)&global_sha3);
|
||||
}
|
||||
|
||||
if (encode_and_hash_field(field_ptr) == false)
|
||||
@@ -158,7 +72,7 @@ static bool encode_and_hash_type(const uint8_t *const struct_ptr)
|
||||
field_ptr = get_next_struct_field(field_ptr);
|
||||
}
|
||||
// closing struct parenthese
|
||||
hash_byte(')');
|
||||
hash_byte(')', (cx_hash_t*)&global_sha3);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -302,9 +216,7 @@ const uint8_t *type_hash(const void *const structs_array,
|
||||
deps += 1;
|
||||
}
|
||||
mem_dealloc(mem_alloc(0) - mem_loc_bak);
|
||||
#ifdef DEBUG
|
||||
PRINTF("\n");
|
||||
#endif
|
||||
|
||||
// End progressive hashing
|
||||
if ((hash_ptr = mem_alloc(KECCAK256_HASH_BYTESIZE)) == NULL)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user