EIP-712 code linting
This commit is contained in:
@@ -34,14 +34,13 @@
|
||||
#define COMMON_CLA 0xB0
|
||||
#define COMMON_INS_GET_WALLET_ID 0x04
|
||||
|
||||
#define APDU_RESPONSE_OK 0x9000
|
||||
#define APDU_RESPONSE_INVALID_DATA 0x6a80
|
||||
#define APDU_RESPONSE_INSUFFICIENT_MEMORY 0x6a84
|
||||
#define APDU_RESPONSE_INVALID_INS 0x6d00
|
||||
#define APDU_RESPONSE_INVALID_P1_P2 0x6b00
|
||||
#define APDU_RESPONSE_CONDITION_NOT_SATISFIED 0x6985
|
||||
#define APDU_RESPONSE_REF_DATA_NOT_USABLE 0x6a88
|
||||
|
||||
#define APDU_RESPONSE_OK 0x9000
|
||||
#define APDU_RESPONSE_INVALID_DATA 0x6a80
|
||||
#define APDU_RESPONSE_INSUFFICIENT_MEMORY 0x6a84
|
||||
#define APDU_RESPONSE_INVALID_INS 0x6d00
|
||||
#define APDU_RESPONSE_INVALID_P1_P2 0x6b00
|
||||
#define APDU_RESPONSE_CONDITION_NOT_SATISFIED 0x6985
|
||||
#define APDU_RESPONSE_REF_DATA_NOT_USABLE 0x6a88
|
||||
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
@@ -63,14 +62,7 @@
|
||||
|
||||
#endif
|
||||
|
||||
enum {
|
||||
OFFSET_CLA = 0,
|
||||
OFFSET_INS,
|
||||
OFFSET_P1,
|
||||
OFFSET_P2,
|
||||
OFFSET_LC,
|
||||
OFFSET_CDATA
|
||||
};
|
||||
enum { OFFSET_CLA = 0, OFFSET_INS, OFFSET_P1, OFFSET_P2, OFFSET_LC, OFFSET_CDATA };
|
||||
|
||||
void handleGetPublicKey(uint8_t p1,
|
||||
uint8_t p2,
|
||||
|
||||
13
src/main.c
13
src/main.c
@@ -71,7 +71,7 @@ const internalStorage_t N_storage_real;
|
||||
chain_config_t *chainConfig;
|
||||
|
||||
void reset_app_context() {
|
||||
//PRINTF("!!RESET_APP_CONTEXT\n");
|
||||
// PRINTF("!!RESET_APP_CONTEXT\n");
|
||||
appState = APP_STATE_IDLE;
|
||||
called_from_swap = false;
|
||||
pluginType = OLD_INTERNAL;
|
||||
@@ -664,8 +664,7 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
|
||||
break;
|
||||
|
||||
case INS_SIGN_EIP_712_MESSAGE:
|
||||
if (G_io_apdu_buffer[OFFSET_P2] == 0)
|
||||
{
|
||||
if (G_io_apdu_buffer[OFFSET_P2] == 0) {
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_ITEMS);
|
||||
handleSignEIP712Message_v0(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
@@ -673,15 +672,13 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
handle_eip712_sign(G_io_apdu_buffer);
|
||||
#else
|
||||
THROW(0x6B00);
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -723,7 +720,7 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
handle_eip712_filtering(G_io_apdu_buffer);
|
||||
break;
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#if 0
|
||||
case 0xFF: // return to dashboard
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef struct internalStorage_t {
|
||||
unsigned char displayNonce;
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
bool verbose_eip712;
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
uint8_t initialized;
|
||||
} internalStorage_t;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ void switch_settings_display_data(void);
|
||||
void switch_settings_display_nonce(void);
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
void switch_settings_verbose_eip712(void);
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// clang-format off
|
||||
@@ -148,27 +148,22 @@ UX_FLOW(ux_settings_flow,
|
||||
&ux_settings_flow_display_nonce_step,
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
&ux_settings_flow_verbose_eip712_step,
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
&ux_settings_flow_back_step);
|
||||
|
||||
void display_settings(const ux_flow_step_t* const start_step) {
|
||||
const char *const values[] = {
|
||||
"Enabled",
|
||||
"Disabled"
|
||||
};
|
||||
bool settings[] = {
|
||||
N_storage.dataAllowed,
|
||||
N_storage.contractDetails,
|
||||
N_storage.displayNonce,
|
||||
const char* const values[] = {"Enabled", "Disabled"};
|
||||
bool settings[] = {N_storage.dataAllowed,
|
||||
N_storage.contractDetails,
|
||||
N_storage.displayNonce,
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
N_storage.verbose_eip712
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
N_storage.verbose_eip712
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
};
|
||||
uint8_t offset = 0;
|
||||
uint8_t increment = MAX(strlen(values[0]), strlen(values[1])) + 1;
|
||||
|
||||
for (unsigned int i = 0; i < (sizeof(settings) / sizeof(settings[0])); ++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < (sizeof(settings) / sizeof(settings[0])); ++i) {
|
||||
strlcpy(strings.common.fullAddress + offset,
|
||||
(settings[i] ? values[0] : values[1]),
|
||||
sizeof(strings.common.fullAddress) - offset);
|
||||
@@ -197,13 +192,12 @@ void switch_settings_display_nonce(void) {
|
||||
}
|
||||
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
void switch_settings_verbose_eip712(void)
|
||||
{
|
||||
void switch_settings_verbose_eip712(void) {
|
||||
bool value = !N_storage.verbose_eip712;
|
||||
nvm_write((void*) &N_storage.verbose_eip712, (void*) &value, sizeof(value));
|
||||
display_settings(&ux_settings_flow_verbose_eip712_step);
|
||||
}
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// clang-format off
|
||||
|
||||
@@ -22,14 +22,13 @@
|
||||
|
||||
#include "uint256.h"
|
||||
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void array_hexstr(char* strbuf, const void* bin, unsigned int len);
|
||||
|
||||
void convertUint128BE(const uint8_t *const data, uint32_t length, uint128_t *const target);
|
||||
void convertUint256BE(const uint8_t *const data, uint32_t length, uint256_t *const target);
|
||||
void convertUint64BEto128(const uint8_t *const data, uint32_t length, uint128_t *const target);
|
||||
void convertUint128BE(const uint8_t* const data, uint32_t length, uint128_t* const target);
|
||||
void convertUint256BE(const uint8_t* const data, uint32_t length, uint256_t* const target);
|
||||
void convertUint64BEto128(const uint8_t* const data, uint32_t length, uint128_t* const target);
|
||||
|
||||
uint64_t u64_from_BE(const uint8_t* in, uint8_t size);
|
||||
|
||||
|
||||
@@ -5,23 +5,20 @@
|
||||
|
||||
#define SIZE_MEM_BUFFER 5120
|
||||
|
||||
static uint8_t mem_buffer[SIZE_MEM_BUFFER];
|
||||
static size_t mem_idx;
|
||||
|
||||
static uint8_t mem_buffer[SIZE_MEM_BUFFER];
|
||||
static size_t mem_idx;
|
||||
|
||||
/**
|
||||
* Initializes the memory buffer index
|
||||
*/
|
||||
void mem_init(void)
|
||||
{
|
||||
void mem_init(void) {
|
||||
mem_idx = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the memory buffer index
|
||||
*/
|
||||
void mem_reset(void)
|
||||
{
|
||||
void mem_reset(void) {
|
||||
mem_init();
|
||||
}
|
||||
|
||||
@@ -34,9 +31,8 @@ void mem_reset(void)
|
||||
* @param[in] size Requested allocation size in bytes
|
||||
* @return Allocated memory pointer; \ref NULL if not enough space left.
|
||||
*/
|
||||
void *mem_alloc(size_t size)
|
||||
{
|
||||
if ((mem_idx + size) > SIZE_MEM_BUFFER) // Buffer exceeded
|
||||
void *mem_alloc(size_t size) {
|
||||
if ((mem_idx + size) > SIZE_MEM_BUFFER) // Buffer exceeded
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -49,16 +45,13 @@ void *mem_alloc(size_t size)
|
||||
*
|
||||
* @param[in] size Requested deallocation size in bytes
|
||||
*/
|
||||
void mem_dealloc(size_t size)
|
||||
{
|
||||
if (size > mem_idx) // More than is already allocated
|
||||
void mem_dealloc(size_t size) {
|
||||
if (size > mem_idx) // More than is already allocated
|
||||
{
|
||||
mem_idx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
mem_idx -= size;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_DYN_MEM_ALLOC
|
||||
#endif // HAVE_DYN_MEM_ALLOC
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void mem_init(void);
|
||||
void mem_reset(void);
|
||||
void *mem_alloc(size_t size);
|
||||
void mem_dealloc(size_t size);
|
||||
void mem_init(void);
|
||||
void mem_reset(void);
|
||||
void *mem_alloc(size_t size);
|
||||
void mem_dealloc(size_t size);
|
||||
|
||||
#endif // HAVE_DYN_MEM_ALLOC
|
||||
#endif // HAVE_DYN_MEM_ALLOC
|
||||
|
||||
#endif // MEM_H_
|
||||
#endif // MEM_H_
|
||||
|
||||
@@ -14,26 +14,22 @@
|
||||
*
|
||||
* @return pointer to memory area or \ref NULL if the allocation failed
|
||||
*/
|
||||
char *mem_alloc_and_format_uint(uint32_t value, uint8_t *const length)
|
||||
{
|
||||
char *mem_ptr;
|
||||
uint32_t value_copy;
|
||||
uint8_t size;
|
||||
char *mem_alloc_and_format_uint(uint32_t value, uint8_t *const length) {
|
||||
char *mem_ptr;
|
||||
uint32_t value_copy;
|
||||
uint8_t size;
|
||||
|
||||
size = 1; // minimum size, even if 0
|
||||
size = 1; // minimum size, even if 0
|
||||
value_copy = value;
|
||||
while (value_copy >= 10)
|
||||
{
|
||||
while (value_copy >= 10) {
|
||||
value_copy /= 10;
|
||||
size += 1;
|
||||
}
|
||||
// +1 for the null character
|
||||
if ((mem_ptr = mem_alloc(sizeof(char) * (size + 1))))
|
||||
{
|
||||
if ((mem_ptr = mem_alloc(sizeof(char) * (size + 1)))) {
|
||||
snprintf(mem_ptr, (size + 1), "%u", value);
|
||||
mem_dealloc(sizeof(char)); // to skip the null character
|
||||
if (length != NULL)
|
||||
{
|
||||
mem_dealloc(sizeof(char)); // to skip the null character
|
||||
if (length != NULL) {
|
||||
*length = size;
|
||||
}
|
||||
}
|
||||
@@ -49,18 +45,16 @@ char *mem_alloc_and_format_uint(uint32_t value, uint8_t *const length)
|
||||
*
|
||||
* @return pointer to the memory area, \ref NULL if the allocation failed
|
||||
*/
|
||||
void *mem_alloc_and_align(size_t size, size_t alignment)
|
||||
{
|
||||
uint8_t align_diff = (uintptr_t)mem_alloc(0) % alignment;
|
||||
void *mem_alloc_and_align(size_t size, size_t alignment) {
|
||||
uint8_t align_diff = (uintptr_t) mem_alloc(0) % alignment;
|
||||
|
||||
if (align_diff > 0) // alignment needed
|
||||
if (align_diff > 0) // alignment needed
|
||||
{
|
||||
if (mem_alloc(alignment - align_diff) == NULL)
|
||||
{
|
||||
if (mem_alloc(alignment - align_diff) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return mem_alloc(size);
|
||||
}
|
||||
|
||||
#endif // HAVE_DYN_MEM_ALLOC
|
||||
#endif // HAVE_DYN_MEM_ALLOC
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MEM_ALLOC_AND_ALIGN_TYPE(type) mem_alloc_and_align(sizeof(type), __alignof__(type))
|
||||
#define MEM_ALLOC_AND_ALIGN_TYPE(type) mem_alloc_and_align(sizeof(type), __alignof__(type))
|
||||
|
||||
char *mem_alloc_and_format_uint(uint32_t value, uint8_t *const written_chars);
|
||||
void *mem_alloc_and_align(size_t size, size_t alignment);
|
||||
char *mem_alloc_and_format_uint(uint32_t value, uint8_t *const written_chars);
|
||||
void *mem_alloc_and_align(size_t size, size_t alignment);
|
||||
|
||||
#endif // HAVE_DYN_MEM_ALLOC
|
||||
#endif // HAVE_DYN_MEM_ALLOC
|
||||
|
||||
#endif // MEM_UTILS_H_
|
||||
#endif // MEM_UTILS_H_
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <string.h>
|
||||
#include "uint128.h"
|
||||
#include "uint_common.h"
|
||||
#include "ethUtils.h" // HEXDIGITS
|
||||
#include "ethUtils.h" // HEXDIGITS
|
||||
|
||||
void readu128BE(const uint8_t *const buffer, uint128_t *const target) {
|
||||
UPPER_P(target) = readUint64BE(buffer);
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#include <string.h>
|
||||
#include "uint256.h"
|
||||
#include "uint_common.h"
|
||||
#include "ethUstream.h" // INT256_LENGTH
|
||||
#include "ethUtils.h" // HEXDIGITS
|
||||
#include "ethUstream.h" // INT256_LENGTH
|
||||
#include "ethUtils.h" // HEXDIGITS
|
||||
|
||||
void readu256BE(const uint8_t *const buffer, uint256_t *const target) {
|
||||
readu128BE(buffer, &UPPER_P(target));
|
||||
|
||||
@@ -58,5 +58,4 @@ bool tostring256_signed(const uint256_t *const number,
|
||||
char *const out,
|
||||
uint32_t out_length);
|
||||
|
||||
|
||||
#endif // _UINT256_H_
|
||||
|
||||
@@ -32,4 +32,4 @@ void read_u64_be(const uint8_t *const in, uint64_t *const out);
|
||||
uint64_t readUint64BE(const uint8_t *const buffer);
|
||||
void reverseString(char *const str, uint32_t length);
|
||||
|
||||
#endif //_UINT_COMMON_H_
|
||||
#endif //_UINT_COMMON_H_
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "commands_712.h"
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "context.h"
|
||||
#include "field_hash.h"
|
||||
#include "path.h"
|
||||
@@ -22,19 +22,16 @@
|
||||
*
|
||||
* @param[in] success whether the command was successful
|
||||
*/
|
||||
void handle_eip712_return_code(bool success)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
void handle_eip712_return_code(bool success) {
|
||||
if (success) {
|
||||
apdu_response_code = APDU_RESPONSE_OK;
|
||||
}
|
||||
*(uint16_t*)G_io_apdu_buffer = __builtin_bswap16(apdu_response_code);
|
||||
*(uint16_t *) G_io_apdu_buffer = __builtin_bswap16(apdu_response_code);
|
||||
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
if (!success) {
|
||||
eip712_context_deinit();
|
||||
}
|
||||
}
|
||||
@@ -45,18 +42,14 @@ void handle_eip712_return_code(bool success)
|
||||
* @param[in] apdu_buf the APDU payload
|
||||
* @return whether the command was successful or not
|
||||
*/
|
||||
bool handle_eip712_struct_def(const uint8_t *const apdu_buf)
|
||||
{
|
||||
bool handle_eip712_struct_def(const uint8_t *const apdu_buf) {
|
||||
bool ret = true;
|
||||
|
||||
if (eip712_context == NULL)
|
||||
{
|
||||
if (eip712_context == NULL) {
|
||||
ret = eip712_context_init();
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
switch (apdu_buf[OFFSET_P2])
|
||||
{
|
||||
if (ret) {
|
||||
switch (apdu_buf[OFFSET_P2]) {
|
||||
case P2_NAME:
|
||||
ret = set_struct_name(apdu_buf[OFFSET_LC], &apdu_buf[OFFSET_CDATA]);
|
||||
break;
|
||||
@@ -65,8 +58,8 @@ bool handle_eip712_struct_def(const uint8_t *const apdu_buf)
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unknown P2 0x%x for APDU 0x%x\n",
|
||||
apdu_buf[OFFSET_P2],
|
||||
apdu_buf[OFFSET_INS]);
|
||||
apdu_buf[OFFSET_P2],
|
||||
apdu_buf[OFFSET_INS]);
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_P1_P2;
|
||||
ret = false;
|
||||
}
|
||||
@@ -81,26 +74,18 @@ bool handle_eip712_struct_def(const uint8_t *const apdu_buf)
|
||||
* @param[in] apdu_buf the APDU payload
|
||||
* @return whether the command was successful or not
|
||||
*/
|
||||
bool handle_eip712_struct_impl(const uint8_t *const apdu_buf)
|
||||
{
|
||||
bool handle_eip712_struct_impl(const uint8_t *const apdu_buf) {
|
||||
bool ret = false;
|
||||
bool reply_apdu = true;
|
||||
|
||||
if (eip712_context == NULL)
|
||||
{
|
||||
if (eip712_context == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (apdu_buf[OFFSET_P2])
|
||||
{
|
||||
} else {
|
||||
switch (apdu_buf[OFFSET_P2]) {
|
||||
case P2_NAME:
|
||||
// set root type
|
||||
if ((ret = path_set_root((char*)&apdu_buf[OFFSET_CDATA],
|
||||
apdu_buf[OFFSET_LC])))
|
||||
{
|
||||
if (N_storage.verbose_eip712)
|
||||
{
|
||||
if ((ret = path_set_root((char *) &apdu_buf[OFFSET_CDATA], apdu_buf[OFFSET_LC]))) {
|
||||
if (N_storage.verbose_eip712) {
|
||||
ui_712_review_struct(path_get_root());
|
||||
reply_apdu = false;
|
||||
}
|
||||
@@ -110,14 +95,12 @@ bool handle_eip712_struct_impl(const uint8_t *const apdu_buf)
|
||||
case P2_FIELD:
|
||||
if ((ret = field_hash(&apdu_buf[OFFSET_CDATA],
|
||||
apdu_buf[OFFSET_LC],
|
||||
apdu_buf[OFFSET_P1] != P1_COMPLETE)))
|
||||
{
|
||||
apdu_buf[OFFSET_P1] != P1_COMPLETE))) {
|
||||
reply_apdu = false;
|
||||
}
|
||||
break;
|
||||
case P2_ARRAY:
|
||||
ret = path_new_array_depth(&apdu_buf[OFFSET_CDATA],
|
||||
apdu_buf[OFFSET_LC]);
|
||||
ret = path_new_array_depth(&apdu_buf[OFFSET_CDATA], apdu_buf[OFFSET_LC]);
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unknown P2 0x%x for APDU 0x%x\n",
|
||||
@@ -126,8 +109,7 @@ bool handle_eip712_struct_impl(const uint8_t *const apdu_buf)
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_P1_P2;
|
||||
}
|
||||
}
|
||||
if (reply_apdu)
|
||||
{
|
||||
if (reply_apdu) {
|
||||
handle_eip712_return_code(ret);
|
||||
}
|
||||
return ret;
|
||||
@@ -139,54 +121,43 @@ bool handle_eip712_struct_impl(const uint8_t *const apdu_buf)
|
||||
* @param[in] apdu_buf the APDU payload
|
||||
* @return whether the command was successful or not
|
||||
*/
|
||||
bool handle_eip712_filtering(const uint8_t *const apdu_buf)
|
||||
{
|
||||
bool handle_eip712_filtering(const uint8_t *const apdu_buf) {
|
||||
bool ret = true;
|
||||
bool reply_apdu = true;
|
||||
e_filtering_type type;
|
||||
|
||||
if (eip712_context == NULL)
|
||||
{
|
||||
if (eip712_context == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (apdu_buf[OFFSET_P1])
|
||||
{
|
||||
} else {
|
||||
switch (apdu_buf[OFFSET_P1]) {
|
||||
case P1_ACTIVATE:
|
||||
if (!N_storage.verbose_eip712)
|
||||
{
|
||||
if (!N_storage.verbose_eip712) {
|
||||
ui_712_set_filtering_mode(EIP712_FILTERING_FULL);
|
||||
ret = compute_schema_hash();
|
||||
}
|
||||
break;
|
||||
case P1_CONTRACT_NAME:
|
||||
case P1_FIELD_NAME:
|
||||
type = (apdu_buf[OFFSET_P1] == P1_CONTRACT_NAME)
|
||||
? FILTERING_CONTRACT_NAME
|
||||
: FILTERING_STRUCT_FIELD;
|
||||
if (ui_712_get_filtering_mode() == EIP712_FILTERING_FULL)
|
||||
{
|
||||
ret = provide_filtering_info(&apdu_buf[OFFSET_CDATA],
|
||||
apdu_buf[OFFSET_LC],
|
||||
type);
|
||||
if ((apdu_buf[OFFSET_P1] == P1_CONTRACT_NAME) && ret)
|
||||
{
|
||||
type = (apdu_buf[OFFSET_P1] == P1_CONTRACT_NAME) ? FILTERING_CONTRACT_NAME
|
||||
: FILTERING_STRUCT_FIELD;
|
||||
if (ui_712_get_filtering_mode() == EIP712_FILTERING_FULL) {
|
||||
ret =
|
||||
provide_filtering_info(&apdu_buf[OFFSET_CDATA], apdu_buf[OFFSET_LC], type);
|
||||
if ((apdu_buf[OFFSET_P1] == P1_CONTRACT_NAME) && ret) {
|
||||
reply_apdu = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unknown P1 0x%x for APDU 0x%x\n",
|
||||
apdu_buf[OFFSET_P1],
|
||||
apdu_buf[OFFSET_INS]);
|
||||
apdu_buf[OFFSET_P1],
|
||||
apdu_buf[OFFSET_INS]);
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_P1_P2;
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
if (reply_apdu)
|
||||
{
|
||||
if (reply_apdu) {
|
||||
handle_eip712_return_code(ret);
|
||||
}
|
||||
return ret;
|
||||
@@ -198,32 +169,24 @@ bool handle_eip712_filtering(const uint8_t *const apdu_buf)
|
||||
* @param[in] apdu_buf the APDU payload
|
||||
* @return whether the command was successful or not
|
||||
*/
|
||||
bool handle_eip712_sign(const uint8_t *const apdu_buf)
|
||||
{
|
||||
bool handle_eip712_sign(const uint8_t *const apdu_buf) {
|
||||
bool ret = false;
|
||||
uint8_t length = apdu_buf[OFFSET_LC];
|
||||
|
||||
if (eip712_context == NULL)
|
||||
{
|
||||
if (eip712_context == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
}
|
||||
else if (parseBip32(&apdu_buf[OFFSET_CDATA],
|
||||
&length,
|
||||
&tmpCtx.messageSigningContext.bip32) != NULL)
|
||||
{
|
||||
if (!N_storage.verbose_eip712 && (ui_712_get_filtering_mode() == EIP712_FILTERING_BASIC))
|
||||
{
|
||||
} else if (parseBip32(&apdu_buf[OFFSET_CDATA], &length, &tmpCtx.messageSigningContext.bip32) !=
|
||||
NULL) {
|
||||
if (!N_storage.verbose_eip712 && (ui_712_get_filtering_mode() == EIP712_FILTERING_BASIC)) {
|
||||
ui_712_message_hash();
|
||||
}
|
||||
ret = true;
|
||||
ui_712_end_sign();
|
||||
}
|
||||
if (!ret)
|
||||
{
|
||||
if (!ret) {
|
||||
handle_eip712_return_code(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -7,27 +7,27 @@
|
||||
#include <stdint.h>
|
||||
|
||||
// APDUs P1
|
||||
#define P1_COMPLETE 0x00
|
||||
#define P1_PARTIAL 0xFF
|
||||
#define P1_ACTIVATE 0x00
|
||||
#define P1_CONTRACT_NAME 0x0F
|
||||
#define P1_FIELD_NAME 0xFF
|
||||
#define P1_COMPLETE 0x00
|
||||
#define P1_PARTIAL 0xFF
|
||||
#define P1_ACTIVATE 0x00
|
||||
#define P1_CONTRACT_NAME 0x0F
|
||||
#define P1_FIELD_NAME 0xFF
|
||||
|
||||
// APDUs P2
|
||||
#define P2_NAME 0x00
|
||||
#define P2_ARRAY 0x0F
|
||||
#define P2_FIELD 0xFF
|
||||
#define P2_KEY 0x00
|
||||
#define P2_VALUE 0xFF
|
||||
#define P2_NAME 0x00
|
||||
#define P2_ARRAY 0x0F
|
||||
#define P2_FIELD 0xFF
|
||||
#define P2_KEY 0x00
|
||||
#define P2_VALUE 0xFF
|
||||
|
||||
#define DOMAIN_STRUCT_NAME "EIP712Domain"
|
||||
#define DOMAIN_STRUCT_NAME "EIP712Domain"
|
||||
|
||||
bool handle_eip712_struct_def(const uint8_t *const apdu_buf);
|
||||
bool handle_eip712_struct_impl(const uint8_t *const apdu_buf);
|
||||
bool handle_eip712_sign(const uint8_t *const apdu_buf);
|
||||
bool handle_eip712_filtering(const uint8_t *const apdu_buf);
|
||||
void handle_eip712_return_code(bool success);
|
||||
bool handle_eip712_struct_def(const uint8_t *const apdu_buf);
|
||||
bool handle_eip712_struct_impl(const uint8_t *const apdu_buf);
|
||||
bool handle_eip712_sign(const uint8_t *const apdu_buf);
|
||||
bool handle_eip712_filtering(const uint8_t *const apdu_buf);
|
||||
void handle_eip712_return_code(bool success);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // EIP712_H_
|
||||
#endif // EIP712_H_
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
#include "field_hash.h"
|
||||
#include "ui_logic.h"
|
||||
#include "typed_data.h"
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "shared_context.h" // reset_app_context
|
||||
#include "ui_callbacks.h" // ui_idle
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "shared_context.h" // reset_app_context
|
||||
#include "ui_callbacks.h" // ui_idle
|
||||
|
||||
s_eip712_context *eip712_context = NULL;
|
||||
|
||||
@@ -21,38 +21,32 @@ s_eip712_context *eip712_context = NULL;
|
||||
*
|
||||
* @return a boolean indicating if the initialization was successful or not
|
||||
*/
|
||||
bool eip712_context_init(void)
|
||||
{
|
||||
bool eip712_context_init(void) {
|
||||
// init global variables
|
||||
mem_init();
|
||||
|
||||
if ((eip712_context = MEM_ALLOC_AND_ALIGN_TYPE(*eip712_context)) == NULL)
|
||||
{
|
||||
if ((eip712_context = MEM_ALLOC_AND_ALIGN_TYPE(*eip712_context)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sol_typenames_init() == false)
|
||||
{
|
||||
if (sol_typenames_init() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (path_init() == false)
|
||||
{
|
||||
if (path_init() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (field_hash_init() == false)
|
||||
{
|
||||
if (field_hash_init() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ui_712_init() == false)
|
||||
{
|
||||
if (ui_712_init() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typed_data_init() == false) // this needs to be initialized last !
|
||||
if (typed_data_init() == false) // this needs to be initialized last !
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -63,8 +57,7 @@ bool eip712_context_init(void)
|
||||
/**
|
||||
* De-initialize the EIP712 context
|
||||
*/
|
||||
void eip712_context_deinit(void)
|
||||
{
|
||||
void eip712_context_deinit(void) {
|
||||
typed_data_deinit();
|
||||
path_deinit();
|
||||
field_hash_deinit();
|
||||
|
||||
@@ -4,19 +4,18 @@
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "ethUstream.h" // ADDRESS_LENGTH
|
||||
#include "ethUstream.h" // ADDRESS_LENGTH
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint8_t contract_addr[ADDRESS_LENGTH];
|
||||
uint8_t schema_hash[224 / 8];
|
||||
} s_eip712_context;
|
||||
} s_eip712_context;
|
||||
|
||||
extern s_eip712_context *eip712_context;
|
||||
|
||||
bool eip712_context_init(void);
|
||||
void eip712_context_deinit(void);
|
||||
bool eip712_context_init(void);
|
||||
void eip712_context_deinit(void);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // EIP712_CTX_H_
|
||||
#endif // EIP712_CTX_H_
|
||||
|
||||
@@ -5,13 +5,9 @@
|
||||
#include "encode_field.h"
|
||||
#include "mem.h"
|
||||
#include "shared_context.h"
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MSB,
|
||||
LSB
|
||||
} e_padding_type;
|
||||
typedef enum { MSB, LSB } e_padding_type;
|
||||
|
||||
/**
|
||||
* Encode a field value to 32 bytes (padded)
|
||||
@@ -25,20 +21,17 @@ typedef enum
|
||||
static void *field_encode(const uint8_t *const value,
|
||||
uint8_t length,
|
||||
e_padding_type ptype,
|
||||
uint8_t pval)
|
||||
{
|
||||
uint8_t pval) {
|
||||
uint8_t *padded_value;
|
||||
uint8_t start_idx;
|
||||
|
||||
if (length > EIP_712_ENCODED_FIELD_LENGTH) // sanity check
|
||||
if (length > EIP_712_ENCODED_FIELD_LENGTH) // sanity check
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return NULL;
|
||||
}
|
||||
if ((padded_value = mem_alloc(EIP_712_ENCODED_FIELD_LENGTH)) != NULL)
|
||||
{
|
||||
switch (ptype)
|
||||
{
|
||||
if ((padded_value = mem_alloc(EIP_712_ENCODED_FIELD_LENGTH)) != NULL) {
|
||||
switch (ptype) {
|
||||
case MSB:
|
||||
memset(padded_value, pval, EIP_712_ENCODED_FIELD_LENGTH - length);
|
||||
start_idx = EIP_712_ENCODED_FIELD_LENGTH - length;
|
||||
@@ -49,12 +42,10 @@ static void *field_encode(const uint8_t *const value,
|
||||
break;
|
||||
default:
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return NULL; // should not be here
|
||||
return NULL; // should not be here
|
||||
}
|
||||
memcpy(&padded_value[start_idx], value, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
return padded_value;
|
||||
@@ -67,8 +58,7 @@ static void *field_encode(const uint8_t *const value,
|
||||
* @param[in] length its byte-length
|
||||
* @return the encoded value
|
||||
*/
|
||||
void *encode_uint(const uint8_t *const value, uint8_t length)
|
||||
{
|
||||
void *encode_uint(const uint8_t *const value, uint8_t length) {
|
||||
// no length check here since it will be checked by field_encode
|
||||
return field_encode(value, length, MSB, 0x00);
|
||||
}
|
||||
@@ -81,16 +71,13 @@ void *encode_uint(const uint8_t *const value, uint8_t length)
|
||||
* @param[in] typesize the type size in bytes
|
||||
* @return the encoded value
|
||||
*/
|
||||
void *encode_int(const uint8_t *const value, uint8_t length, uint8_t typesize)
|
||||
{
|
||||
void *encode_int(const uint8_t *const value, uint8_t length, uint8_t typesize) {
|
||||
uint8_t padding_value;
|
||||
|
||||
if ((length == typesize) && (value[0] & (1 << 7))) // negative number
|
||||
if ((length == typesize) && (value[0] & (1 << 7))) // negative number
|
||||
{
|
||||
padding_value = 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
padding_value = 0x00;
|
||||
}
|
||||
// no length check here since it will be checked by field_encode
|
||||
@@ -104,8 +91,7 @@ void *encode_int(const uint8_t *const value, uint8_t length, uint8_t typesize
|
||||
* @param[in] length its byte-length
|
||||
* @return the encoded value
|
||||
*/
|
||||
void *encode_bytes(const uint8_t *const value, uint8_t length)
|
||||
{
|
||||
void *encode_bytes(const uint8_t *const value, uint8_t length) {
|
||||
// no length check here since it will be checked by field_encode
|
||||
return field_encode(value, length, LSB, 0x00);
|
||||
}
|
||||
@@ -117,14 +103,13 @@ void *encode_bytes(const uint8_t *const value, uint8_t length)
|
||||
* @param[in] length its byte-length
|
||||
* @return the encoded value
|
||||
*/
|
||||
void *encode_boolean(const bool *const value, uint8_t length)
|
||||
{
|
||||
if (length != 1) // sanity check
|
||||
void *encode_boolean(const bool *const value, uint8_t length) {
|
||||
if (length != 1) // sanity check
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return NULL;
|
||||
}
|
||||
return encode_uint((uint8_t*)value, length);
|
||||
return encode_uint((uint8_t *) value, length);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,9 +119,8 @@ void *encode_boolean(const bool *const value, uint8_t length)
|
||||
* @param[in] length its byte-length
|
||||
* @return the encoded value
|
||||
*/
|
||||
void *encode_address(const uint8_t *const value, uint8_t length)
|
||||
{
|
||||
if (length != ADDRESS_LENGTH) // sanity check
|
||||
void *encode_address(const uint8_t *const value, uint8_t length) {
|
||||
if (length != ADDRESS_LENGTH) // sanity check
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return NULL;
|
||||
@@ -144,4 +128,4 @@ void *encode_address(const uint8_t *const value, uint8_t length)
|
||||
return encode_uint(value, length);
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define EIP_712_ENCODED_FIELD_LENGTH 32
|
||||
#define EIP_712_ENCODED_FIELD_LENGTH 32
|
||||
|
||||
void *encode_uint(const uint8_t *const value, uint8_t length);
|
||||
void *encode_int(const uint8_t *const value, uint8_t length, uint8_t typesize);
|
||||
void *encode_boolean(const bool *const value, uint8_t length);
|
||||
void *encode_address(const uint8_t *const value, uint8_t length);
|
||||
void *encode_bytes(const uint8_t *const value, uint8_t length);
|
||||
void *encode_uint(const uint8_t *const value, uint8_t length);
|
||||
void *encode_int(const uint8_t *const value, uint8_t length, uint8_t typesize);
|
||||
void *encode_boolean(const bool *const value, uint8_t length);
|
||||
void *encode_address(const uint8_t *const value, uint8_t length);
|
||||
void *encode_bytes(const uint8_t *const value, uint8_t length);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // ENCODE_FIELD_H_
|
||||
#endif // ENCODE_FIELD_H_
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
#include "mem_utils.h"
|
||||
#include "shared_context.h"
|
||||
#include "ui_logic.h"
|
||||
#include "ethUtils.h" // KECCAK256_HASH_BYTESIZE
|
||||
#include "context.h" // contract_addr
|
||||
#include "utils.h" // u64_from_BE
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "ethUtils.h" // KECCAK256_HASH_BYTESIZE
|
||||
#include "context.h" // contract_addr
|
||||
#include "utils.h" // u64_from_BE
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "typed_data.h"
|
||||
#include "commands_712.h"
|
||||
#include "hash_bytes.h"
|
||||
@@ -23,12 +23,9 @@ static s_field_hashing *fh = NULL;
|
||||
*
|
||||
* @return whether the initialization was successful or not
|
||||
*/
|
||||
bool field_hash_init(void)
|
||||
{
|
||||
if (fh == NULL)
|
||||
{
|
||||
if ((fh = MEM_ALLOC_AND_ALIGN_TYPE(*fh)) == NULL)
|
||||
{
|
||||
bool field_hash_init(void) {
|
||||
if (fh == NULL) {
|
||||
if ((fh = MEM_ALLOC_AND_ALIGN_TYPE(*fh)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
@@ -40,8 +37,7 @@ bool field_hash_init(void)
|
||||
/**
|
||||
* Deinitialize the field hash context
|
||||
*/
|
||||
void field_hash_deinit(void)
|
||||
{
|
||||
void field_hash_deinit(void) {
|
||||
fh = NULL;
|
||||
}
|
||||
|
||||
@@ -55,18 +51,16 @@ void field_hash_deinit(void)
|
||||
*/
|
||||
static const uint8_t *field_hash_prepare(const void *const field_ptr,
|
||||
const uint8_t *data,
|
||||
uint8_t *data_length)
|
||||
{
|
||||
uint8_t *data_length) {
|
||||
e_type field_type;
|
||||
|
||||
field_type = struct_field_type(field_ptr);
|
||||
fh->remaining_size = __builtin_bswap16(*(uint16_t*)&data[0]); // network byte order
|
||||
fh->remaining_size = __builtin_bswap16(*(uint16_t *) &data[0]); // network byte order
|
||||
data += sizeof(uint16_t);
|
||||
*data_length -= sizeof(uint16_t);
|
||||
fh->state = FHS_WAITING_FOR_MORE;
|
||||
if (IS_DYN(field_type))
|
||||
{
|
||||
cx_keccak_init(&global_sha3, 256); // init hash
|
||||
if (IS_DYN(field_type)) {
|
||||
cx_keccak_init(&global_sha3, 256); // init hash
|
||||
ui_712_new_field(field_ptr, data, *data_length);
|
||||
}
|
||||
return data;
|
||||
@@ -84,14 +78,12 @@ static const uint8_t *field_hash_prepare(const void *const field_ptr,
|
||||
*/
|
||||
static const uint8_t *field_hash_finalize_static(const void *const field_ptr,
|
||||
const uint8_t *const data,
|
||||
uint8_t data_length)
|
||||
{
|
||||
uint8_t data_length) {
|
||||
uint8_t *value = NULL;
|
||||
e_type field_type;
|
||||
|
||||
field_type = struct_field_type(field_ptr);
|
||||
switch (field_type)
|
||||
{
|
||||
switch (field_type) {
|
||||
case TYPE_SOL_INT:
|
||||
value = encode_int(data, data_length, get_struct_field_typesize(field_ptr));
|
||||
break;
|
||||
@@ -105,7 +97,7 @@ static const uint8_t *field_hash_finalize_static(const void *const field_ptr,
|
||||
value = encode_address(data, data_length);
|
||||
break;
|
||||
case TYPE_SOL_BOOL:
|
||||
value = encode_boolean((bool*)data, data_length);
|
||||
value = encode_boolean((bool *) data, data_length);
|
||||
break;
|
||||
case TYPE_CUSTOM:
|
||||
default:
|
||||
@@ -113,8 +105,7 @@ static const uint8_t *field_hash_finalize_static(const void *const field_ptr,
|
||||
PRINTF("Unknown solidity type!\n");
|
||||
}
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
if (value == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ui_712_new_field(field_ptr, data, data_length);
|
||||
@@ -128,22 +119,15 @@ static const uint8_t *field_hash_finalize_static(const void *const field_ptr,
|
||||
*
|
||||
* @return pointer to the hash, \ref NULL if it failed
|
||||
*/
|
||||
static uint8_t *field_hash_finalize_dynamic(void)
|
||||
{
|
||||
static uint8_t *field_hash_finalize_dynamic(void) {
|
||||
uint8_t *value;
|
||||
|
||||
if ((value = mem_alloc(KECCAK256_HASH_BYTESIZE)) == NULL)
|
||||
{
|
||||
if ((value = mem_alloc(KECCAK256_HASH_BYTESIZE)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
// copy hash into memory
|
||||
cx_hash((cx_hash_t*)&global_sha3,
|
||||
CX_LAST,
|
||||
NULL,
|
||||
0,
|
||||
value,
|
||||
KECCAK256_HASH_BYTESIZE);
|
||||
cx_hash((cx_hash_t *) &global_sha3, CX_LAST, NULL, 0, value, KECCAK256_HASH_BYTESIZE);
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -153,24 +137,20 @@ static uint8_t *field_hash_finalize_dynamic(void)
|
||||
* @param[in] field_type the struct field's type
|
||||
* @param[in] hash the field hash
|
||||
*/
|
||||
static void field_hash_feed_parent(e_type field_type, const uint8_t *const hash)
|
||||
{
|
||||
static void field_hash_feed_parent(e_type field_type, const uint8_t *const hash) {
|
||||
uint8_t len;
|
||||
|
||||
if (IS_DYN(field_type))
|
||||
{
|
||||
if (IS_DYN(field_type)) {
|
||||
len = KECCAK256_HASH_BYTESIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
len = EIP_712_ENCODED_FIELD_LENGTH;
|
||||
}
|
||||
|
||||
// last thing in mem is the hash of the previous field
|
||||
// and just before it is the current hash context
|
||||
cx_sha3_t *hash_ctx = (cx_sha3_t*)(hash - sizeof(cx_sha3_t));
|
||||
cx_sha3_t *hash_ctx = (cx_sha3_t *) (hash - sizeof(cx_sha3_t));
|
||||
// continue the progressive hash on it
|
||||
hash_nbytes(hash, len, (cx_hash_t*)hash_ctx);
|
||||
hash_nbytes(hash, len, (cx_hash_t *) hash_ctx);
|
||||
// deallocate it
|
||||
mem_dealloc(len);
|
||||
}
|
||||
@@ -187,29 +167,23 @@ static void field_hash_feed_parent(e_type field_type, const uint8_t *const hash)
|
||||
*/
|
||||
static bool field_hash_domain_special_fields(const void *const field_ptr,
|
||||
const uint8_t *const data,
|
||||
uint8_t data_length)
|
||||
{
|
||||
uint8_t data_length) {
|
||||
const char *key;
|
||||
uint8_t keylen;
|
||||
|
||||
key = get_struct_field_keyname(field_ptr, &keylen);
|
||||
// copy contract address into context
|
||||
if (strncmp(key, "verifyingContract", keylen) == 0)
|
||||
{
|
||||
if (data_length != sizeof(eip712_context->contract_addr))
|
||||
{
|
||||
if (strncmp(key, "verifyingContract", keylen) == 0) {
|
||||
if (data_length != sizeof(eip712_context->contract_addr)) {
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
PRINTF("Unexpected verifyingContract length!\n");
|
||||
return false;
|
||||
}
|
||||
memcpy(eip712_context->contract_addr, data, data_length);
|
||||
}
|
||||
else if (strncmp(key, "chainId", keylen) == 0)
|
||||
{
|
||||
} else if (strncmp(key, "chainId", keylen) == 0) {
|
||||
uint64_t chainId = u64_from_BE(data, data_length);
|
||||
|
||||
if (chainId != chainConfig->chainId)
|
||||
{
|
||||
if (chainId != chainConfig->chainId) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
PRINTF("EIP712Domain chain ID mismatch, expected 0x%.*h, got 0x%.*h !\n",
|
||||
sizeof(chainConfig->chainId),
|
||||
@@ -232,35 +206,25 @@ static bool field_hash_domain_special_fields(const void *const field_ptr,
|
||||
*/
|
||||
static bool field_hash_finalize(const void *const field_ptr,
|
||||
const uint8_t *const data,
|
||||
uint8_t data_length)
|
||||
{
|
||||
uint8_t data_length) {
|
||||
const uint8_t *value = NULL;
|
||||
e_type field_type;
|
||||
|
||||
field_type = struct_field_type(field_ptr);
|
||||
if (!IS_DYN(field_type))
|
||||
{
|
||||
if ((value = field_hash_finalize_static(field_ptr,
|
||||
data,
|
||||
data_length)) == NULL)
|
||||
{
|
||||
if (!IS_DYN(field_type)) {
|
||||
if ((value = field_hash_finalize_static(field_ptr, data, data_length)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((value = field_hash_finalize_dynamic()) == NULL)
|
||||
{
|
||||
} else {
|
||||
if ((value = field_hash_finalize_dynamic()) == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
field_hash_feed_parent(field_type, value);
|
||||
|
||||
if (path_get_root_type() == ROOT_DOMAIN)
|
||||
{
|
||||
if (field_hash_domain_special_fields(field_ptr, data, data_length) == false)
|
||||
{
|
||||
if (path_get_root_type() == ROOT_DOMAIN) {
|
||||
if (field_hash_domain_special_fields(field_ptr, data, data_length) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -278,50 +242,40 @@ static bool field_hash_finalize(const void *const field_ptr,
|
||||
* @param[in] partial whether there is more of that data coming later or not
|
||||
* @return whether the data hashing was successful or not
|
||||
*/
|
||||
bool field_hash(const uint8_t *data,
|
||||
uint8_t data_length,
|
||||
bool partial)
|
||||
{
|
||||
bool field_hash(const uint8_t *data, uint8_t data_length, bool partial) {
|
||||
const void *field_ptr;
|
||||
e_type field_type;
|
||||
|
||||
if ((fh == NULL) || ((field_ptr = path_get_field()) == NULL))
|
||||
{
|
||||
if ((fh == NULL) || ((field_ptr = path_get_field()) == NULL)) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
|
||||
field_type = struct_field_type(field_ptr);
|
||||
if (fh->state == FHS_IDLE) // first packet for this frame
|
||||
if (fh->state == FHS_IDLE) // first packet for this frame
|
||||
{
|
||||
data = field_hash_prepare(field_ptr, data, &data_length);
|
||||
}
|
||||
if (data_length > fh->remaining_size)
|
||||
{
|
||||
if (data_length > fh->remaining_size) {
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
fh->remaining_size -= data_length;
|
||||
// if a dynamic type -> continue progressive hash
|
||||
if (IS_DYN(field_type))
|
||||
{
|
||||
hash_nbytes(data, data_length, (cx_hash_t*)&global_sha3);
|
||||
if (IS_DYN(field_type)) {
|
||||
hash_nbytes(data, data_length, (cx_hash_t *) &global_sha3);
|
||||
}
|
||||
if (fh->remaining_size == 0)
|
||||
{
|
||||
if (partial) // only makes sense if marked as complete
|
||||
if (fh->remaining_size == 0) {
|
||||
if (partial) // only makes sense if marked as complete
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if (field_hash_finalize(field_ptr, data, data_length) == false)
|
||||
{
|
||||
if (field_hash_finalize(field_ptr, data, data_length) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!partial || !IS_DYN(field_type)) // only makes sense if marked as partial
|
||||
} else {
|
||||
if (!partial || !IS_DYN(field_type)) // only makes sense if marked as partial
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
@@ -332,4 +286,4 @@ bool field_hash(const uint8_t *data,
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -6,26 +6,19 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define IS_DYN(type) (((type) == TYPE_SOL_STRING) || ((type) == TYPE_SOL_BYTES_DYN))
|
||||
#define IS_DYN(type) (((type) == TYPE_SOL_STRING) || ((type) == TYPE_SOL_BYTES_DYN))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FHS_IDLE,
|
||||
FHS_WAITING_FOR_MORE
|
||||
} e_field_hashing_state;
|
||||
typedef enum { FHS_IDLE, FHS_WAITING_FOR_MORE } e_field_hashing_state;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t remaining_size;
|
||||
uint8_t state; // e_field_hashing_state
|
||||
} s_field_hashing;
|
||||
typedef struct {
|
||||
uint16_t remaining_size;
|
||||
uint8_t state; // e_field_hashing_state
|
||||
} s_field_hashing;
|
||||
|
||||
bool field_hash_init(void);
|
||||
void field_hash_deinit(void);
|
||||
bool field_hash(const uint8_t *data,
|
||||
uint8_t data_length,
|
||||
bool partial);
|
||||
bool field_hash(const uint8_t *data, uint8_t data_length, bool partial);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // FIELD_HASH_H_
|
||||
#endif // FIELD_HASH_H_
|
||||
|
||||
@@ -2,59 +2,49 @@
|
||||
|
||||
#include "filtering.h"
|
||||
#include "hash_bytes.h"
|
||||
#include "ethUstream.h" // INT256_LENGTH
|
||||
#include "apdu_constants.h" // APDU return codes
|
||||
#include "ethUstream.h" // INT256_LENGTH
|
||||
#include "apdu_constants.h" // APDU return codes
|
||||
#include "context.h"
|
||||
#include "commands_712.h"
|
||||
#include "typed_data.h"
|
||||
#include "path.h"
|
||||
#include "ui_logic.h"
|
||||
|
||||
|
||||
#ifdef HAVE_EIP712_TESTING_KEY
|
||||
static const uint8_t EIP712_FEEDER_PUBLIC_KEY[] = {
|
||||
0x04, 0x4c, 0xca, 0x8f, 0xad, 0x49, 0x6a, 0xa5, 0x04, 0x0a, 0x00, 0xa7, 0xeb, 0x2f,
|
||||
0x5c, 0xc3, 0xb8, 0x53, 0x76, 0xd8, 0x8b, 0xa1, 0x47, 0xa7, 0xd7, 0x05, 0x4a, 0x99,
|
||||
0xc6, 0x40, 0x56, 0x18, 0x87, 0xfe, 0x17, 0xa0, 0x96, 0xe3, 0x6c, 0x3b, 0x52, 0x3b,
|
||||
0x24, 0x4f, 0x3e, 0x2f, 0xf7, 0xf8, 0x40, 0xae, 0x26, 0xc4, 0xe7, 0x7a, 0xd3, 0xbc,
|
||||
0x73, 0x9a, 0xf5, 0xde, 0x6f, 0x2d, 0x77, 0xa7, 0xb6
|
||||
};
|
||||
#endif // HAVE_EIP712_TESTING_KEY
|
||||
|
||||
0x04, 0x4c, 0xca, 0x8f, 0xad, 0x49, 0x6a, 0xa5, 0x04, 0x0a, 0x00, 0xa7, 0xeb,
|
||||
0x2f, 0x5c, 0xc3, 0xb8, 0x53, 0x76, 0xd8, 0x8b, 0xa1, 0x47, 0xa7, 0xd7, 0x05,
|
||||
0x4a, 0x99, 0xc6, 0x40, 0x56, 0x18, 0x87, 0xfe, 0x17, 0xa0, 0x96, 0xe3, 0x6c,
|
||||
0x3b, 0x52, 0x3b, 0x24, 0x4f, 0x3e, 0x2f, 0xf7, 0xf8, 0x40, 0xae, 0x26, 0xc4,
|
||||
0xe7, 0x7a, 0xd3, 0xbc, 0x73, 0x9a, 0xf5, 0xde, 0x6f, 0x2d, 0x77, 0xa7, 0xb6};
|
||||
#endif // HAVE_EIP712_TESTING_KEY
|
||||
|
||||
/**
|
||||
* Reconstruct the field path and hash it
|
||||
*
|
||||
* @param[in] hash_ctx the hashing context
|
||||
*/
|
||||
static void hash_filtering_path(cx_hash_t *const hash_ctx)
|
||||
{
|
||||
static void hash_filtering_path(cx_hash_t *const hash_ctx) {
|
||||
const void *field_ptr;
|
||||
const char *key;
|
||||
uint8_t key_len;
|
||||
|
||||
for (uint8_t i = 0; i < path_get_depth_count(); ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
for (uint8_t i = 0; i < path_get_depth_count(); ++i) {
|
||||
if (i > 0) {
|
||||
hash_byte('.', hash_ctx);
|
||||
}
|
||||
if ((field_ptr = path_get_nth_field(i + 1)) != NULL)
|
||||
{
|
||||
if ((key = get_struct_field_keyname(field_ptr, &key_len)) != NULL)
|
||||
{
|
||||
if ((field_ptr = path_get_nth_field(i + 1)) != NULL) {
|
||||
if ((key = get_struct_field_keyname(field_ptr, &key_len)) != NULL) {
|
||||
// field name
|
||||
hash_nbytes((uint8_t*)key, key_len, hash_ctx);
|
||||
hash_nbytes((uint8_t *) key, key_len, hash_ctx);
|
||||
|
||||
// array levels
|
||||
if (struct_field_is_array(field_ptr))
|
||||
{
|
||||
if (struct_field_is_array(field_ptr)) {
|
||||
uint8_t lvl_count;
|
||||
|
||||
get_struct_field_array_lvls_array(field_ptr, &lvl_count);
|
||||
for (int j = 0; j < lvl_count; ++j)
|
||||
{
|
||||
hash_nbytes((uint8_t*)".[]", 3, hash_ctx);
|
||||
for (int j = 0; j < lvl_count; ++j) {
|
||||
hash_nbytes((uint8_t *) ".[]", 3, hash_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,8 +66,7 @@ static bool verify_filtering_signature(uint8_t dname_length,
|
||||
const char *const dname,
|
||||
uint8_t sig_length,
|
||||
const uint8_t *const sig,
|
||||
e_filtering_type type)
|
||||
{
|
||||
e_filtering_type type) {
|
||||
uint8_t hash[INT256_LENGTH];
|
||||
cx_ecfp_public_key_t verifying_key;
|
||||
cx_sha256_t hash_ctx;
|
||||
@@ -87,35 +76,27 @@ static bool verify_filtering_signature(uint8_t dname_length,
|
||||
|
||||
// Chain ID
|
||||
chain_id = __builtin_bswap64(chainConfig->chainId);
|
||||
hash_nbytes((uint8_t*)&chain_id, sizeof(chain_id), (cx_hash_t*)&hash_ctx);
|
||||
hash_nbytes((uint8_t *) &chain_id, sizeof(chain_id), (cx_hash_t *) &hash_ctx);
|
||||
|
||||
// Contract address
|
||||
hash_nbytes(eip712_context->contract_addr,
|
||||
sizeof(eip712_context->contract_addr),
|
||||
(cx_hash_t*)&hash_ctx);
|
||||
(cx_hash_t *) &hash_ctx);
|
||||
|
||||
// Schema hash
|
||||
hash_nbytes(eip712_context->schema_hash,
|
||||
sizeof(eip712_context->schema_hash),
|
||||
(cx_hash_t*)&hash_ctx);
|
||||
(cx_hash_t *) &hash_ctx);
|
||||
|
||||
if (type == FILTERING_STRUCT_FIELD)
|
||||
{
|
||||
hash_filtering_path((cx_hash_t*)&hash_ctx);
|
||||
if (type == FILTERING_STRUCT_FIELD) {
|
||||
hash_filtering_path((cx_hash_t *) &hash_ctx);
|
||||
}
|
||||
|
||||
// Display name
|
||||
hash_nbytes((uint8_t*)dname,
|
||||
sizeof(char) * dname_length,
|
||||
(cx_hash_t*)&hash_ctx);
|
||||
hash_nbytes((uint8_t *) dname, sizeof(char) * dname_length, (cx_hash_t *) &hash_ctx);
|
||||
|
||||
// Finalize hash
|
||||
cx_hash((cx_hash_t*)&hash_ctx,
|
||||
CX_LAST,
|
||||
NULL,
|
||||
0,
|
||||
hash,
|
||||
INT256_LENGTH);
|
||||
cx_hash((cx_hash_t *) &hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH);
|
||||
|
||||
cx_ecfp_init_public_key(CX_CURVE_256K1,
|
||||
#ifdef HAVE_EIP712_TESTING_KEY
|
||||
@@ -126,14 +107,7 @@ static bool verify_filtering_signature(uint8_t dname_length,
|
||||
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
||||
#endif
|
||||
&verifying_key);
|
||||
if (!cx_ecdsa_verify(&verifying_key,
|
||||
CX_LAST,
|
||||
CX_SHA256,
|
||||
hash,
|
||||
sizeof(hash),
|
||||
sig,
|
||||
sig_length))
|
||||
{
|
||||
if (!cx_ecdsa_verify(&verifying_key, CX_LAST, CX_SHA256, hash, sizeof(hash), sig, sig_length)) {
|
||||
#ifndef HAVE_BYPASS_SIGNATURES
|
||||
PRINTF("Invalid EIP-712 filtering signature\n");
|
||||
return false;
|
||||
@@ -150,56 +124,42 @@ static bool verify_filtering_signature(uint8_t dname_length,
|
||||
* @param[in] type the type of filtering
|
||||
* @return if everything went well or not
|
||||
*/
|
||||
bool provide_filtering_info(const uint8_t *const payload,
|
||||
uint8_t length,
|
||||
e_filtering_type type)
|
||||
{
|
||||
bool provide_filtering_info(const uint8_t *const payload, uint8_t length, e_filtering_type type) {
|
||||
bool ret = false;
|
||||
uint8_t dname_len;
|
||||
const char *dname;
|
||||
uint8_t sig_len;
|
||||
const uint8_t *sig;
|
||||
|
||||
if (type == FILTERING_CONTRACT_NAME)
|
||||
if (type == FILTERING_CONTRACT_NAME) {
|
||||
if (path_get_root_type() != ROOT_DOMAIN) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
} else // FILTERING_STRUCT_FIELD
|
||||
{
|
||||
if (path_get_root_type() != ROOT_DOMAIN)
|
||||
{
|
||||
if (path_get_root_type() != ROOT_MESSAGE) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else // FILTERING_STRUCT_FIELD
|
||||
{
|
||||
if (path_get_root_type() != ROOT_MESSAGE)
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (length > 0)
|
||||
{
|
||||
if (length > 0) {
|
||||
dname_len = payload[0];
|
||||
if ((1 + dname_len) < length)
|
||||
{
|
||||
dname = (char*)&payload[1];
|
||||
if ((1 + dname_len) < length) {
|
||||
dname = (char *) &payload[1];
|
||||
sig_len = payload[1 + dname_len];
|
||||
sig = &payload[1 + dname_len + 1];
|
||||
if ((sig_len > 0) && ((1 + dname_len + 1 + sig_len) == length))
|
||||
{
|
||||
if ((ret = verify_filtering_signature(dname_len, dname, sig_len, sig, type)))
|
||||
{
|
||||
if (type == FILTERING_CONTRACT_NAME)
|
||||
{
|
||||
if (!N_storage.verbose_eip712)
|
||||
{
|
||||
if ((sig_len > 0) && ((1 + dname_len + 1 + sig_len) == length)) {
|
||||
if ((ret = verify_filtering_signature(dname_len, dname, sig_len, sig, type))) {
|
||||
if (type == FILTERING_CONTRACT_NAME) {
|
||||
if (!N_storage.verbose_eip712) {
|
||||
ui_712_set_title("Contract", 8);
|
||||
ui_712_set_value(dname, dname_len);
|
||||
ui_712_redraw_generic_step();
|
||||
}
|
||||
}
|
||||
else // FILTERING_STRUCT_FIELD
|
||||
} else // FILTERING_STRUCT_FIELD
|
||||
{
|
||||
if (dname_len > 0) // don't substitute for an empty name
|
||||
if (dname_len > 0) // don't substitute for an empty name
|
||||
{
|
||||
ui_712_set_title(dname, dname_len);
|
||||
}
|
||||
@@ -212,4 +172,4 @@ bool provide_filtering_info(const uint8_t *const payload,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -6,16 +6,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FILTERING_CONTRACT_NAME,
|
||||
FILTERING_STRUCT_FIELD
|
||||
} e_filtering_type;
|
||||
typedef enum { FILTERING_CONTRACT_NAME, FILTERING_STRUCT_FIELD } e_filtering_type;
|
||||
|
||||
bool provide_filtering_info(const uint8_t *const payload,
|
||||
uint8_t length,
|
||||
e_filtering_type type);
|
||||
bool provide_filtering_info(const uint8_t *const payload, uint8_t length, e_filtering_type type);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // FILTERING_H_
|
||||
#endif // FILTERING_H_
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "mem_utils.h"
|
||||
#include "commands_712.h"
|
||||
#include "hash_bytes.h"
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "typed_data.h"
|
||||
|
||||
/**
|
||||
@@ -15,18 +15,16 @@
|
||||
* @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)
|
||||
{
|
||||
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))
|
||||
{
|
||||
switch (struct_field_type(field_ptr)) {
|
||||
case TYPE_SOL_INT:
|
||||
case TYPE_SOL_UINT:
|
||||
field_size *= 8; // bytes -> bits
|
||||
field_size *= 8; // bytes -> bits
|
||||
break;
|
||||
case TYPE_SOL_BYTES_FIX:
|
||||
break;
|
||||
@@ -35,12 +33,11 @@ static bool format_hash_field_type_size(const void *const field_ptr, cx_hash_t *
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if ((uint_str_ptr = mem_alloc_and_format_uint(field_size, &uint_str_len)) == NULL)
|
||||
{
|
||||
if ((uint_str_ptr = mem_alloc_and_format_uint(field_size, &uint_str_len)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
hash_nbytes((uint8_t*)uint_str_ptr, uint_str_len, hash_ctx);
|
||||
hash_nbytes((uint8_t *) uint_str_ptr, uint_str_len, hash_ctx);
|
||||
mem_dealloc(uint_str_len);
|
||||
return true;
|
||||
}
|
||||
@@ -52,8 +49,7 @@ static bool format_hash_field_type_size(const void *const field_ptr, cx_hash_t *
|
||||
* @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)
|
||||
{
|
||||
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;
|
||||
@@ -61,21 +57,18 @@ static bool format_hash_field_type_array_levels(const void *const field_ptr, cx_
|
||||
uint8_t lvls_count;
|
||||
|
||||
lvl_ptr = get_struct_field_array_lvls_array(field_ptr, &lvls_count);
|
||||
while (lvls_count-- > 0)
|
||||
{
|
||||
while (lvls_count-- > 0) {
|
||||
hash_byte('[', hash_ctx);
|
||||
|
||||
switch (struct_field_array_depth(lvl_ptr, &array_size))
|
||||
{
|
||||
switch (struct_field_array_depth(lvl_ptr, &array_size)) {
|
||||
case ARRAY_DYNAMIC:
|
||||
break;
|
||||
case ARRAY_FIXED_SIZE:
|
||||
if ((uint_str_ptr = mem_alloc_and_format_uint(array_size, &uint_str_len)) == NULL)
|
||||
{
|
||||
if ((uint_str_ptr = mem_alloc_and_format_uint(array_size, &uint_str_len)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
hash_nbytes((uint8_t*)uint_str_ptr, uint_str_len, hash_ctx);
|
||||
hash_nbytes((uint8_t *) uint_str_ptr, uint_str_len, hash_ctx);
|
||||
mem_dealloc(uint_str_len);
|
||||
break;
|
||||
default:
|
||||
@@ -96,33 +89,28 @@ static bool format_hash_field_type_array_levels(const void *const field_ptr, cx_
|
||||
* @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)
|
||||
{
|
||||
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);
|
||||
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))
|
||||
{
|
||||
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))
|
||||
{
|
||||
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
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
#include "cx.h"
|
||||
|
||||
bool format_hash_field_type(const void *const field_ptr, cx_hash_t *hash_ctx);
|
||||
bool format_hash_field_type(const void *const field_ptr, cx_hash_t *hash_ctx);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // FORMAT_HASH_FIELD_TYPE_H_
|
||||
#endif // FORMAT_HASH_FIELD_TYPE_H_
|
||||
|
||||
@@ -9,14 +9,8 @@
|
||||
* @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 *const hash_ctx)
|
||||
{
|
||||
cx_hash(hash_ctx,
|
||||
0,
|
||||
bytes_ptr,
|
||||
n,
|
||||
NULL,
|
||||
0);
|
||||
void hash_nbytes(const uint8_t *const bytes_ptr, uint8_t n, cx_hash_t *const hash_ctx) {
|
||||
cx_hash(hash_ctx, 0, bytes_ptr, n, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,9 +19,8 @@ void hash_nbytes(const uint8_t *const bytes_ptr, uint8_t n, cx_hash_t *const has
|
||||
* @param[in] byte byte to hash
|
||||
* @param[in] hash_ctx pointer to the hashing context
|
||||
*/
|
||||
void hash_byte(uint8_t byte, cx_hash_t *const hash_ctx)
|
||||
{
|
||||
void hash_byte(uint8_t byte, cx_hash_t *const hash_ctx) {
|
||||
hash_nbytes(&byte, 1, hash_ctx);
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
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 // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // HASH_BYTES_H_
|
||||
#endif // HASH_BYTES_H_
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "ethUtils.h"
|
||||
#include "mem_utils.h"
|
||||
#include "ui_logic.h"
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "typed_data.h"
|
||||
|
||||
static s_path *path_struct = NULL;
|
||||
@@ -23,46 +23,37 @@ static s_path *path_struct = NULL;
|
||||
* @param[in] n the number of depths to evaluate
|
||||
* @return the feld which the first Nth depths points to
|
||||
*/
|
||||
static const void *get_nth_field(uint8_t *const fields_count_ptr,
|
||||
uint8_t n)
|
||||
{
|
||||
static const void *get_nth_field(uint8_t *const fields_count_ptr, uint8_t n) {
|
||||
const void *struct_ptr = path_struct->root_struct;
|
||||
const void *field_ptr = NULL;
|
||||
const char *typename;
|
||||
uint8_t length;
|
||||
uint8_t fields_count;
|
||||
|
||||
if (path_struct == NULL)
|
||||
if (path_struct == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (n > path_struct->depth_count) // sanity check
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (n > path_struct->depth_count) // sanity check
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
for (uint8_t depth = 0; depth < n; ++depth)
|
||||
{
|
||||
for (uint8_t depth = 0; depth < n; ++depth) {
|
||||
field_ptr = get_struct_fields_array(struct_ptr, &fields_count);
|
||||
|
||||
if (fields_count_ptr != NULL)
|
||||
{
|
||||
if (fields_count_ptr != NULL) {
|
||||
*fields_count_ptr = fields_count;
|
||||
}
|
||||
// check if the index at this depth makes sense
|
||||
if (path_struct->depths[depth] > fields_count)
|
||||
{
|
||||
if (path_struct->depths[depth] > fields_count) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < path_struct->depths[depth]; ++index)
|
||||
{
|
||||
for (uint8_t index = 0; index < path_struct->depths[depth]; ++index) {
|
||||
field_ptr = get_next_struct_field(field_ptr);
|
||||
}
|
||||
if (struct_field_type(field_ptr) == TYPE_CUSTOM)
|
||||
{
|
||||
if (struct_field_type(field_ptr) == TYPE_CUSTOM) {
|
||||
typename = get_struct_field_typename(field_ptr, &length);
|
||||
if ((struct_ptr = get_structn(typename, length)) == NULL)
|
||||
{
|
||||
if ((struct_ptr = get_structn(typename, length)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -76,8 +67,7 @@ static const void *get_nth_field(uint8_t *const fields_count_ptr,
|
||||
* @param[out] the number of fields in the depth of the returned field
|
||||
* @return the field which the path points to
|
||||
*/
|
||||
static inline const void *get_field(uint8_t *const fields_count)
|
||||
{
|
||||
static inline const void *get_field(uint8_t *const fields_count) {
|
||||
return get_nth_field(fields_count, path_struct->depth_count);
|
||||
}
|
||||
|
||||
@@ -87,8 +77,7 @@ static inline const void *get_field(uint8_t *const fields_count)
|
||||
* @param[in] n nth depth requested
|
||||
* @return pointer to the matching field, \ref NULL otherwise
|
||||
*/
|
||||
const void *path_get_nth_field(uint8_t n)
|
||||
{
|
||||
const void *path_get_nth_field(uint8_t n) {
|
||||
return get_nth_field(NULL, n);
|
||||
}
|
||||
|
||||
@@ -98,16 +87,14 @@ const void *path_get_nth_field(uint8_t n)
|
||||
* @param[in] n nth to last depth requested
|
||||
* @return pointer to the matching field, \ref NULL otherwise
|
||||
*/
|
||||
const void *path_get_nth_field_to_last(uint8_t n)
|
||||
{
|
||||
const void *path_get_nth_field_to_last(uint8_t n) {
|
||||
const char *typename;
|
||||
uint8_t typename_len;
|
||||
const void *field_ptr;
|
||||
const void *struct_ptr = NULL;
|
||||
|
||||
field_ptr = get_nth_field(NULL, path_struct->depth_count - n);
|
||||
if (field_ptr != NULL)
|
||||
{
|
||||
if (field_ptr != NULL) {
|
||||
typename = get_struct_field_typename(field_ptr, &typename_len);
|
||||
struct_ptr = get_structn(typename, typename_len);
|
||||
}
|
||||
@@ -119,8 +106,7 @@ const void *path_get_nth_field_to_last(uint8_t n)
|
||||
*
|
||||
* @return the field which the path points to
|
||||
*/
|
||||
const void *path_get_field(void)
|
||||
{
|
||||
const void *path_get_field(void) {
|
||||
return get_field(NULL);
|
||||
}
|
||||
|
||||
@@ -129,14 +115,11 @@ const void *path_get_field(void)
|
||||
*
|
||||
* @return whether the push was succesful
|
||||
*/
|
||||
static bool path_depth_list_push(void)
|
||||
{
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
static bool path_depth_list_push(void) {
|
||||
if (path_struct == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (path_struct->depth_count == MAX_PATH_DEPTH)
|
||||
{
|
||||
if (path_struct->depth_count == MAX_PATH_DEPTH) {
|
||||
return false;
|
||||
}
|
||||
path_struct->depths[path_struct->depth_count] = 0;
|
||||
@@ -149,9 +132,8 @@ static bool path_depth_list_push(void)
|
||||
*
|
||||
* @return pointer to the hashing context
|
||||
*/
|
||||
static cx_sha3_t *get_last_hash_ctx(void)
|
||||
{
|
||||
return (cx_sha3_t*)mem_alloc(0) - 1;
|
||||
static cx_sha3_t *get_last_hash_ctx(void) {
|
||||
return (cx_sha3_t *) mem_alloc(0) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,19 +141,13 @@ static cx_sha3_t *get_last_hash_ctx(void)
|
||||
*
|
||||
* @param[out] hash pointer to buffer where the hash will be stored
|
||||
*/
|
||||
static void finalize_hash_depth(uint8_t *hash)
|
||||
{
|
||||
static void finalize_hash_depth(uint8_t *hash) {
|
||||
const cx_sha3_t *hash_ctx;
|
||||
|
||||
hash_ctx = get_last_hash_ctx();
|
||||
// finalize hash
|
||||
cx_hash((cx_hash_t*)hash_ctx,
|
||||
CX_LAST,
|
||||
NULL,
|
||||
0,
|
||||
hash,
|
||||
KECCAK256_HASH_BYTESIZE);
|
||||
mem_dealloc(sizeof(*hash_ctx)); // remove hash context
|
||||
cx_hash((cx_hash_t *) hash_ctx, CX_LAST, NULL, 0, hash, KECCAK256_HASH_BYTESIZE);
|
||||
mem_dealloc(sizeof(*hash_ctx)); // remove hash context
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,18 +155,12 @@ static void finalize_hash_depth(uint8_t *hash)
|
||||
*
|
||||
* @param[in] hash pointer to given hash
|
||||
*/
|
||||
static void feed_last_hash_depth(const uint8_t *const hash)
|
||||
{
|
||||
static void feed_last_hash_depth(const uint8_t *const hash) {
|
||||
const cx_sha3_t *hash_ctx;
|
||||
|
||||
hash_ctx = get_last_hash_ctx();
|
||||
// continue progressive hash with the array hash
|
||||
cx_hash((cx_hash_t*)hash_ctx,
|
||||
0,
|
||||
hash,
|
||||
KECCAK256_HASH_BYTESIZE,
|
||||
NULL,
|
||||
0);
|
||||
cx_hash((cx_hash_t *) hash_ctx, 0, hash, KECCAK256_HASH_BYTESIZE, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,18 +169,15 @@ static void feed_last_hash_depth(const uint8_t *const hash)
|
||||
* @param[in] init if the hashing context should be initialized
|
||||
* @return whether the memory allocation of the hashing context was successful
|
||||
*/
|
||||
static bool push_new_hash_depth(bool init)
|
||||
{
|
||||
static bool push_new_hash_depth(bool init) {
|
||||
cx_sha3_t *hash_ctx;
|
||||
|
||||
// allocate new hash context
|
||||
if ((hash_ctx = MEM_ALLOC_AND_ALIGN_TYPE(*hash_ctx)) == NULL)
|
||||
{
|
||||
if ((hash_ctx = MEM_ALLOC_AND_ALIGN_TYPE(*hash_ctx)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (init)
|
||||
{
|
||||
cx_keccak_init(hash_ctx, 256); // initialize it
|
||||
if (init) {
|
||||
cx_keccak_init(hash_ctx, 256); // initialize it
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -220,38 +187,27 @@ static bool push_new_hash_depth(bool init)
|
||||
*
|
||||
* @return whether the pop was successful
|
||||
*/
|
||||
static bool path_depth_list_pop(void)
|
||||
{
|
||||
static bool path_depth_list_pop(void) {
|
||||
uint8_t hash[KECCAK256_HASH_BYTESIZE];
|
||||
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
if (path_struct == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (path_struct->depth_count == 0)
|
||||
{
|
||||
if (path_struct->depth_count == 0) {
|
||||
return false;
|
||||
}
|
||||
path_struct->depth_count -= 1;
|
||||
|
||||
finalize_hash_depth(hash);
|
||||
if (path_struct->depth_count > 0)
|
||||
{
|
||||
if (path_struct->depth_count > 0) {
|
||||
feed_last_hash_depth(hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (path_struct->root_type)
|
||||
{
|
||||
} else {
|
||||
switch (path_struct->root_type) {
|
||||
case ROOT_DOMAIN:
|
||||
memcpy(tmpCtx.messageSigningContext712.domainHash,
|
||||
hash,
|
||||
KECCAK256_HASH_BYTESIZE);
|
||||
memcpy(tmpCtx.messageSigningContext712.domainHash, hash, KECCAK256_HASH_BYTESIZE);
|
||||
break;
|
||||
case ROOT_MESSAGE:
|
||||
memcpy(tmpCtx.messageSigningContext712.messageHash,
|
||||
hash,
|
||||
KECCAK256_HASH_BYTESIZE);
|
||||
memcpy(tmpCtx.messageSigningContext712.messageHash, hash, KECCAK256_HASH_BYTESIZE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -268,17 +224,14 @@ static bool path_depth_list_pop(void)
|
||||
* @param[in] the number of elements contained in that depth
|
||||
* @return whether the push was successful
|
||||
*/
|
||||
static bool array_depth_list_push(uint8_t path_idx, uint8_t size)
|
||||
{
|
||||
static bool array_depth_list_push(uint8_t path_idx, uint8_t size) {
|
||||
s_array_depth *arr;
|
||||
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
if (path_struct == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
if (path_struct->array_depth_count == MAX_ARRAY_DEPTH)
|
||||
{
|
||||
if (path_struct->array_depth_count == MAX_ARRAY_DEPTH) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
@@ -295,16 +248,13 @@ static bool array_depth_list_push(uint8_t path_idx, uint8_t size)
|
||||
*
|
||||
* @return whether the pop was successful
|
||||
*/
|
||||
static bool array_depth_list_pop(void)
|
||||
{
|
||||
static bool array_depth_list_pop(void) {
|
||||
uint8_t hash[KECCAK256_HASH_BYTESIZE];
|
||||
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
if (path_struct == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (path_struct->array_depth_count == 0)
|
||||
{
|
||||
if (path_struct->array_depth_count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -321,8 +271,7 @@ static bool array_depth_list_pop(void)
|
||||
*
|
||||
* @return whether the path update worked or not
|
||||
*/
|
||||
static bool path_update(void)
|
||||
{
|
||||
static bool path_update(void) {
|
||||
uint8_t fields_count;
|
||||
const void *struct_ptr;
|
||||
const void *field_ptr;
|
||||
@@ -330,34 +279,27 @@ static bool path_update(void)
|
||||
uint8_t typename_len;
|
||||
uint8_t hash[KECCAK256_HASH_BYTESIZE];
|
||||
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
if (path_struct == NULL) {
|
||||
return false;
|
||||
}
|
||||
if ((field_ptr = get_field(NULL)) == NULL)
|
||||
{
|
||||
if ((field_ptr = get_field(NULL)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
struct_ptr = path_struct->root_struct;
|
||||
while (struct_field_type(field_ptr) == TYPE_CUSTOM)
|
||||
{
|
||||
while (struct_field_type(field_ptr) == TYPE_CUSTOM) {
|
||||
typename = get_struct_field_typename(field_ptr, &typename_len);
|
||||
if ((struct_ptr = get_structn(typename, typename_len)) == NULL)
|
||||
{
|
||||
if ((struct_ptr = get_structn(typename, typename_len)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
if ((field_ptr = get_struct_fields_array(struct_ptr, &fields_count)) == NULL)
|
||||
{
|
||||
if ((field_ptr = get_struct_fields_array(struct_ptr, &fields_count)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (push_new_hash_depth(true) == false)
|
||||
{
|
||||
if (push_new_hash_depth(true) == false) {
|
||||
return false;
|
||||
}
|
||||
// get the struct typehash
|
||||
if (type_hash(typename, typename_len, hash) == false)
|
||||
{
|
||||
if (type_hash(typename, typename_len, hash) == false) {
|
||||
return false;
|
||||
}
|
||||
feed_last_hash_depth(hash);
|
||||
@@ -375,23 +317,19 @@ static bool path_update(void)
|
||||
* @param[in] name_length the root struct name length
|
||||
* @return boolean indicating if it was successful or not
|
||||
*/
|
||||
bool path_set_root(const char *const struct_name, uint8_t name_length)
|
||||
{
|
||||
bool path_set_root(const char *const struct_name, uint8_t name_length) {
|
||||
uint8_t hash[KECCAK256_HASH_BYTESIZE];
|
||||
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
if (path_struct == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
|
||||
path_struct->root_struct = get_structn(struct_name, name_length);
|
||||
|
||||
if (path_struct->root_struct == NULL)
|
||||
{
|
||||
if (path_struct->root_struct == NULL) {
|
||||
PRINTF("Struct name not found (");
|
||||
for (int i = 0; i < name_length; ++i)
|
||||
{
|
||||
for (int i = 0; i < name_length; ++i) {
|
||||
PRINTF("%c", struct_name[i]);
|
||||
}
|
||||
PRINTF(")!\n");
|
||||
@@ -399,12 +337,10 @@ bool path_set_root(const char *const struct_name, uint8_t name_length)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (push_new_hash_depth(true) == false)
|
||||
{
|
||||
if (push_new_hash_depth(true) == false) {
|
||||
return false;
|
||||
}
|
||||
if (type_hash(struct_name, name_length, hash) == false)
|
||||
{
|
||||
if (type_hash(struct_name, name_length, hash) == false) {
|
||||
return false;
|
||||
}
|
||||
feed_last_hash_depth(hash);
|
||||
@@ -418,12 +354,9 @@ bool path_set_root(const char *const struct_name, uint8_t name_length)
|
||||
path_struct->array_depth_count = 0;
|
||||
|
||||
if ((name_length == strlen(DOMAIN_STRUCT_NAME)) &&
|
||||
(strncmp(struct_name, DOMAIN_STRUCT_NAME, name_length) == 0))
|
||||
{
|
||||
(strncmp(struct_name, DOMAIN_STRUCT_NAME, name_length) == 0)) {
|
||||
path_struct->root_type = ROOT_DOMAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
path_struct->root_type = ROOT_MESSAGE;
|
||||
}
|
||||
|
||||
@@ -444,32 +377,26 @@ bool path_set_root(const char *const struct_name, uint8_t name_length)
|
||||
static bool check_and_add_array_depth(const void *depth,
|
||||
uint8_t total_count,
|
||||
uint8_t pidx,
|
||||
uint8_t size)
|
||||
{
|
||||
uint8_t size) {
|
||||
uint8_t expected_size;
|
||||
uint8_t arr_idx;
|
||||
e_array_type expected_type;
|
||||
|
||||
arr_idx = (total_count - path_struct->array_depth_count) - 1;
|
||||
// we skip index 0, since we already have it
|
||||
for (uint8_t idx = 1; idx < (arr_idx + 1); ++idx)
|
||||
{
|
||||
if ((depth = get_next_struct_field_array_lvl(depth)) == NULL)
|
||||
{
|
||||
for (uint8_t idx = 1; idx < (arr_idx + 1); ++idx) {
|
||||
if ((depth = get_next_struct_field_array_lvl(depth)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
expected_type = struct_field_array_depth(depth, &expected_size);
|
||||
if ((expected_type == ARRAY_FIXED_SIZE) && (expected_size != size))
|
||||
{
|
||||
if ((expected_type == ARRAY_FIXED_SIZE) && (expected_size != size)) {
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
PRINTF("Unexpected array depth size. (expected %d, got %d)\n",
|
||||
expected_size, size);
|
||||
PRINTF("Unexpected array depth size. (expected %d, got %d)\n", expected_size, size);
|
||||
return false;
|
||||
}
|
||||
// add it
|
||||
if (!array_depth_list_push(pidx, size))
|
||||
{
|
||||
if (!array_depth_list_push(pidx, size)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -482,9 +409,7 @@ static bool check_and_add_array_depth(const void *depth,
|
||||
* @param[in] length length of data
|
||||
* @return whether the add was successful or not
|
||||
*/
|
||||
bool path_new_array_depth(const uint8_t *const data,
|
||||
uint8_t length)
|
||||
{
|
||||
bool path_new_array_depth(const uint8_t *const data, uint8_t length) {
|
||||
const void *field_ptr = NULL;
|
||||
const void *depth = NULL;
|
||||
uint8_t depth_count;
|
||||
@@ -492,36 +417,27 @@ bool path_new_array_depth(const uint8_t *const data,
|
||||
uint8_t pidx;
|
||||
bool is_custom;
|
||||
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
if (path_struct == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
else if (length != 1)
|
||||
{
|
||||
} else if (length != 1) {
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (pidx = 0; pidx < path_struct->depth_count; ++pidx)
|
||||
{
|
||||
if ((field_ptr = get_nth_field(NULL, pidx + 1)) == NULL)
|
||||
{
|
||||
for (pidx = 0; pidx < path_struct->depth_count; ++pidx) {
|
||||
if ((field_ptr = get_nth_field(NULL, pidx + 1)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
if (struct_field_is_array(field_ptr))
|
||||
{
|
||||
if ((depth = get_struct_field_array_lvls_array(field_ptr, &depth_count)) == NULL)
|
||||
{
|
||||
if (struct_field_is_array(field_ptr)) {
|
||||
if ((depth = get_struct_field_array_lvls_array(field_ptr, &depth_count)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
total_count += depth_count;
|
||||
if (total_count > path_struct->array_depth_count)
|
||||
{
|
||||
if (!check_and_add_array_depth(depth, total_count, pidx, *data))
|
||||
{
|
||||
if (total_count > path_struct->array_depth_count) {
|
||||
if (!check_and_add_array_depth(depth, total_count, pidx, *data)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -529,24 +445,21 @@ bool path_new_array_depth(const uint8_t *const data,
|
||||
}
|
||||
}
|
||||
|
||||
if (pidx == path_struct->depth_count)
|
||||
{
|
||||
if (pidx == path_struct->depth_count) {
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
PRINTF("Did not find a matching array type.\n");
|
||||
return false;
|
||||
}
|
||||
is_custom = struct_field_type(field_ptr) == TYPE_CUSTOM;
|
||||
if (push_new_hash_depth(!is_custom) == false)
|
||||
{
|
||||
if (push_new_hash_depth(!is_custom) == false) {
|
||||
return false;
|
||||
}
|
||||
if (is_custom)
|
||||
{
|
||||
if (is_custom) {
|
||||
cx_sha3_t *hash_ctx = get_last_hash_ctx();
|
||||
cx_sha3_t *old_ctx = hash_ctx - 1;
|
||||
|
||||
memcpy(hash_ctx, old_ctx, sizeof(*old_ctx));
|
||||
cx_keccak_init(old_ctx, 256); // init hash
|
||||
cx_keccak_init(old_ctx, 256); // init hash
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -557,27 +470,22 @@ bool path_new_array_depth(const uint8_t *const data,
|
||||
*
|
||||
* @return whether the end of the struct has been reached.
|
||||
*/
|
||||
static bool path_advance_in_struct(void)
|
||||
{
|
||||
static bool path_advance_in_struct(void) {
|
||||
bool end_reached = true;
|
||||
uint8_t *depth = &path_struct->depths[path_struct->depth_count - 1];
|
||||
uint8_t fields_count;
|
||||
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
if (path_struct == NULL) {
|
||||
return false;
|
||||
}
|
||||
if ((get_field(&fields_count)) == NULL)
|
||||
{
|
||||
if ((get_field(&fields_count)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (path_struct->depth_count > 0)
|
||||
{
|
||||
if (path_struct->depth_count > 0) {
|
||||
*depth += 1;
|
||||
end_reached = (*depth == fields_count);
|
||||
}
|
||||
if (end_reached)
|
||||
{
|
||||
if (end_reached) {
|
||||
path_depth_list_pop();
|
||||
}
|
||||
return end_reached;
|
||||
@@ -588,36 +496,28 @@ static bool path_advance_in_struct(void)
|
||||
*
|
||||
* @return whether the end of the array levels has been reached.
|
||||
*/
|
||||
static bool path_advance_in_array(void)
|
||||
{
|
||||
static bool path_advance_in_array(void) {
|
||||
bool end_reached;
|
||||
s_array_depth *arr_depth;
|
||||
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
if (path_struct == NULL) {
|
||||
return false;
|
||||
}
|
||||
do
|
||||
{
|
||||
do {
|
||||
end_reached = false;
|
||||
arr_depth = &path_struct->array_depths[path_struct->array_depth_count - 1];
|
||||
|
||||
if ((path_struct->array_depth_count > 0) &&
|
||||
(arr_depth->path_index == (path_struct->depth_count - 1)))
|
||||
{
|
||||
(arr_depth->path_index == (path_struct->depth_count - 1))) {
|
||||
arr_depth->size -= 1;
|
||||
if (arr_depth->size == 0)
|
||||
{
|
||||
if (arr_depth->size == 0) {
|
||||
array_depth_list_pop();
|
||||
end_reached = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (end_reached);
|
||||
} while (end_reached);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -626,22 +526,16 @@ static bool path_advance_in_array(void)
|
||||
*
|
||||
* @return whether the advancement was successful or not
|
||||
*/
|
||||
bool path_advance(void)
|
||||
{
|
||||
bool path_advance(void) {
|
||||
bool end_reached;
|
||||
|
||||
do
|
||||
{
|
||||
if (path_advance_in_array())
|
||||
{
|
||||
do {
|
||||
if (path_advance_in_array()) {
|
||||
end_reached = path_advance_in_struct();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
end_reached = false;
|
||||
}
|
||||
}
|
||||
while (end_reached);
|
||||
} while (end_reached);
|
||||
path_update();
|
||||
return true;
|
||||
}
|
||||
@@ -651,10 +545,8 @@ bool path_advance(void)
|
||||
*
|
||||
* @return enum representing root type
|
||||
*/
|
||||
e_root_type path_get_root_type(void)
|
||||
{
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
e_root_type path_get_root_type(void) {
|
||||
if (path_struct == NULL) {
|
||||
return ROOT_DOMAIN;
|
||||
}
|
||||
return path_struct->root_type;
|
||||
@@ -665,10 +557,8 @@ e_root_type path_get_root_type(void)
|
||||
*
|
||||
* @return pointer to the root structure definition
|
||||
*/
|
||||
const void *path_get_root(void)
|
||||
{
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
const void *path_get_root(void) {
|
||||
if (path_struct == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return path_struct->root_struct;
|
||||
@@ -679,10 +569,8 @@ const void *path_get_root(void)
|
||||
*
|
||||
* @return depth count
|
||||
*/
|
||||
uint8_t path_get_depth_count(void)
|
||||
{
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
uint8_t path_get_depth_count(void) {
|
||||
if (path_struct == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return path_struct->depth_count;
|
||||
@@ -693,16 +581,11 @@ uint8_t path_get_depth_count(void)
|
||||
*
|
||||
* @return whether the memory allocation were successful.
|
||||
*/
|
||||
bool path_init(void)
|
||||
{
|
||||
if (path_struct == NULL)
|
||||
{
|
||||
if ((path_struct = MEM_ALLOC_AND_ALIGN_TYPE(*path_struct)) == NULL)
|
||||
{
|
||||
bool path_init(void) {
|
||||
if (path_struct == NULL) {
|
||||
if ((path_struct = MEM_ALLOC_AND_ALIGN_TYPE(*path_struct)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
path_struct->depth_count = 0;
|
||||
}
|
||||
}
|
||||
@@ -712,9 +595,8 @@ bool path_init(void)
|
||||
/**
|
||||
* De-initialize the path context
|
||||
*/
|
||||
void path_deinit(void)
|
||||
{
|
||||
void path_deinit(void) {
|
||||
path_struct = NULL;
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -9,41 +9,34 @@
|
||||
#define MAX_PATH_DEPTH 16
|
||||
#define MAX_ARRAY_DEPTH 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint8_t path_index;
|
||||
uint8_t size;
|
||||
} s_array_depth;
|
||||
} s_array_depth;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ROOT_DOMAIN,
|
||||
ROOT_MESSAGE
|
||||
} e_root_type;
|
||||
typedef enum { ROOT_DOMAIN, ROOT_MESSAGE } e_root_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint8_t depth_count;
|
||||
uint8_t depths[MAX_PATH_DEPTH];
|
||||
uint8_t array_depth_count;
|
||||
s_array_depth array_depths[MAX_ARRAY_DEPTH];
|
||||
const void *root_struct;
|
||||
e_root_type root_type;
|
||||
} s_path;
|
||||
} s_path;
|
||||
|
||||
bool path_set_root(const char *const struct_name, uint8_t length);
|
||||
const void *path_get_field(void);
|
||||
bool path_advance(void);
|
||||
bool path_init(void);
|
||||
void path_deinit(void);
|
||||
bool path_new_array_depth(const uint8_t *const data,
|
||||
uint8_t length);
|
||||
bool path_set_root(const char *const struct_name, uint8_t length);
|
||||
const void *path_get_field(void);
|
||||
bool path_advance(void);
|
||||
bool path_init(void);
|
||||
void path_deinit(void);
|
||||
bool path_new_array_depth(const uint8_t *const data, uint8_t length);
|
||||
e_root_type path_get_root_type(void);
|
||||
const void *path_get_root(void);
|
||||
const void *path_get_root(void);
|
||||
const void *path_get_nth_field(uint8_t n);
|
||||
const void *path_get_nth_field_to_last(uint8_t n);
|
||||
uint8_t path_get_depth_count(void);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // PATH_H_
|
||||
#endif // PATH_H_
|
||||
|
||||
@@ -19,8 +19,7 @@ typedef cx_sha256_t cx_sha224_t;
|
||||
*
|
||||
* @return whether the schema hash was successful or not
|
||||
*/
|
||||
bool compute_schema_hash(void)
|
||||
{
|
||||
bool compute_schema_hash(void) {
|
||||
const void *struct_ptr;
|
||||
uint8_t structs_count;
|
||||
const void *field_ptr;
|
||||
@@ -32,42 +31,37 @@ bool compute_schema_hash(void)
|
||||
cx_sha224_init(&hash_ctx);
|
||||
|
||||
struct_ptr = get_structs_array(&structs_count);
|
||||
hash_byte('{', (cx_hash_t*)&hash_ctx);
|
||||
while (structs_count-- > 0)
|
||||
{
|
||||
hash_byte('{', (cx_hash_t *) &hash_ctx);
|
||||
while (structs_count-- > 0) {
|
||||
name = get_struct_name(struct_ptr, &name_length);
|
||||
hash_byte('"', (cx_hash_t*)&hash_ctx);
|
||||
hash_nbytes((uint8_t*)name, name_length, (cx_hash_t*)&hash_ctx);
|
||||
hash_nbytes((uint8_t*)"\":[", 3, (cx_hash_t*)&hash_ctx);
|
||||
hash_byte('"', (cx_hash_t *) &hash_ctx);
|
||||
hash_nbytes((uint8_t *) name, name_length, (cx_hash_t *) &hash_ctx);
|
||||
hash_nbytes((uint8_t *) "\":[", 3, (cx_hash_t *) &hash_ctx);
|
||||
field_ptr = get_struct_fields_array(struct_ptr, &fields_count);
|
||||
while (fields_count-- > 0)
|
||||
{
|
||||
hash_nbytes((uint8_t*)"{\"name\":\"", 9, (cx_hash_t*)&hash_ctx);
|
||||
while (fields_count-- > 0) {
|
||||
hash_nbytes((uint8_t *) "{\"name\":\"", 9, (cx_hash_t *) &hash_ctx);
|
||||
name = get_struct_field_keyname(field_ptr, &name_length);
|
||||
hash_nbytes((uint8_t*)name, name_length, (cx_hash_t*)&hash_ctx);
|
||||
hash_nbytes((uint8_t*)"\",\"type\":\"", 10, (cx_hash_t*)&hash_ctx);
|
||||
if (!format_hash_field_type(field_ptr, (cx_hash_t*)&hash_ctx))
|
||||
{
|
||||
hash_nbytes((uint8_t *) name, name_length, (cx_hash_t *) &hash_ctx);
|
||||
hash_nbytes((uint8_t *) "\",\"type\":\"", 10, (cx_hash_t *) &hash_ctx);
|
||||
if (!format_hash_field_type(field_ptr, (cx_hash_t *) &hash_ctx)) {
|
||||
return false;
|
||||
}
|
||||
hash_nbytes((uint8_t*)"\"}", 2, (cx_hash_t*)&hash_ctx);
|
||||
if (fields_count > 0)
|
||||
{
|
||||
hash_byte(',', (cx_hash_t*)&hash_ctx);
|
||||
hash_nbytes((uint8_t *) "\"}", 2, (cx_hash_t *) &hash_ctx);
|
||||
if (fields_count > 0) {
|
||||
hash_byte(',', (cx_hash_t *) &hash_ctx);
|
||||
}
|
||||
field_ptr = get_next_struct_field(field_ptr);
|
||||
}
|
||||
hash_byte(']', (cx_hash_t*)&hash_ctx);
|
||||
if (structs_count > 0)
|
||||
{
|
||||
hash_byte(',', (cx_hash_t*)&hash_ctx);
|
||||
hash_byte(']', (cx_hash_t *) &hash_ctx);
|
||||
if (structs_count > 0) {
|
||||
hash_byte(',', (cx_hash_t *) &hash_ctx);
|
||||
}
|
||||
struct_ptr = get_next_struct(struct_ptr);
|
||||
}
|
||||
hash_byte('}', (cx_hash_t*)&hash_ctx);
|
||||
hash_byte('}', (cx_hash_t *) &hash_ctx);
|
||||
|
||||
// copy hash into context struct
|
||||
cx_hash((cx_hash_t*)&hash_ctx,
|
||||
cx_hash((cx_hash_t *) &hash_ctx,
|
||||
CX_LAST,
|
||||
NULL,
|
||||
0,
|
||||
@@ -76,4 +70,4 @@ bool compute_schema_hash(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool compute_schema_hash(void);
|
||||
bool compute_schema_hash(void);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // SCHEMA_HASH_H_
|
||||
#endif // SCHEMA_HASH_H_
|
||||
|
||||
@@ -5,21 +5,16 @@
|
||||
#include "sol_typenames.h"
|
||||
#include "mem.h"
|
||||
#include "os_pic.h"
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "typed_data.h"
|
||||
#include "utils.h" // ARRAY_SIZE
|
||||
#include "utils.h" // ARRAY_SIZE
|
||||
|
||||
// Bit indicating they are more types associated to this typename
|
||||
#define TYPENAME_MORE_TYPE (1 << 7)
|
||||
#define TYPENAME_MORE_TYPE (1 << 7)
|
||||
|
||||
static uint8_t *sol_typenames = NULL;
|
||||
|
||||
enum
|
||||
{
|
||||
IDX_ENUM = 0,
|
||||
IDX_STR_IDX,
|
||||
IDX_COUNT
|
||||
};
|
||||
enum { IDX_ENUM = 0, IDX_STR_IDX, IDX_COUNT };
|
||||
|
||||
/**
|
||||
* Find a match between a typename index and all the type enums associated to it
|
||||
@@ -28,21 +23,19 @@ enum
|
||||
* @param[in] t_idx typename index
|
||||
* @return whether at least one match was found
|
||||
*/
|
||||
static bool find_enum_matches(const uint8_t enum_to_idx[TYPES_COUNT - 1][IDX_COUNT], uint8_t t_idx)
|
||||
{
|
||||
static bool find_enum_matches(const uint8_t enum_to_idx[TYPES_COUNT - 1][IDX_COUNT],
|
||||
uint8_t t_idx) {
|
||||
uint8_t *enum_match = NULL;
|
||||
|
||||
// loop over enum/typename pairs
|
||||
for (uint8_t e_idx = 0; e_idx < (TYPES_COUNT - 1); ++e_idx)
|
||||
{
|
||||
if (t_idx == enum_to_idx[e_idx][IDX_STR_IDX]) // match
|
||||
for (uint8_t e_idx = 0; e_idx < (TYPES_COUNT - 1); ++e_idx) {
|
||||
if (t_idx == enum_to_idx[e_idx][IDX_STR_IDX]) // match
|
||||
{
|
||||
if (enum_match != NULL) // in case of a previous match, mark it
|
||||
if (enum_match != NULL) // in case of a previous match, mark it
|
||||
{
|
||||
*enum_match |= TYPENAME_MORE_TYPE;
|
||||
}
|
||||
if ((enum_match = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if ((enum_match = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
@@ -57,8 +50,7 @@ static bool find_enum_matches(const uint8_t enum_to_idx[TYPES_COUNT - 1][IDX_COU
|
||||
*
|
||||
* @return whether the initialization went well or not
|
||||
*/
|
||||
bool sol_typenames_init(void)
|
||||
{
|
||||
bool sol_typenames_init(void) {
|
||||
const char *const typenames[] = {
|
||||
"int", // 0
|
||||
"uint", // 1
|
||||
@@ -68,39 +60,32 @@ bool sol_typenames_init(void)
|
||||
"bytes" // 5
|
||||
};
|
||||
// \ref TYPES_COUNT - 1 since we don't include \ref TYPE_CUSTOM
|
||||
const uint8_t enum_to_idx[TYPES_COUNT - 1][IDX_COUNT] = {
|
||||
{ TYPE_SOL_INT, 0 },
|
||||
{ TYPE_SOL_UINT, 1 },
|
||||
{ TYPE_SOL_ADDRESS, 2 },
|
||||
{ TYPE_SOL_BOOL, 3 },
|
||||
{ TYPE_SOL_STRING, 4 },
|
||||
{ TYPE_SOL_BYTES_FIX, 5 },
|
||||
{ TYPE_SOL_BYTES_DYN, 5 }
|
||||
};
|
||||
const uint8_t enum_to_idx[TYPES_COUNT - 1][IDX_COUNT] = {{TYPE_SOL_INT, 0},
|
||||
{TYPE_SOL_UINT, 1},
|
||||
{TYPE_SOL_ADDRESS, 2},
|
||||
{TYPE_SOL_BOOL, 3},
|
||||
{TYPE_SOL_STRING, 4},
|
||||
{TYPE_SOL_BYTES_FIX, 5},
|
||||
{TYPE_SOL_BYTES_DYN, 5}};
|
||||
uint8_t *typename_len_ptr;
|
||||
char *typename_ptr;
|
||||
|
||||
if ((sol_typenames = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if ((sol_typenames = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
return false;
|
||||
}
|
||||
*(sol_typenames) = 0;
|
||||
// loop over typenames
|
||||
for (uint8_t t_idx = 0; t_idx < ARRAY_SIZE(typenames); ++t_idx)
|
||||
{
|
||||
for (uint8_t t_idx = 0; t_idx < ARRAY_SIZE(typenames); ++t_idx) {
|
||||
// if at least one match was found
|
||||
if (find_enum_matches(enum_to_idx, t_idx))
|
||||
{
|
||||
if ((typename_len_ptr = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if (find_enum_matches(enum_to_idx, t_idx)) {
|
||||
if ((typename_len_ptr = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
// get pointer to the allocated space just above
|
||||
*typename_len_ptr = strlen(PIC(typenames[t_idx]));
|
||||
|
||||
if ((typename_ptr = mem_alloc(sizeof(char) * *typename_len_ptr)) == NULL)
|
||||
{
|
||||
if ((typename_ptr = mem_alloc(sizeof(char) * *typename_len_ptr)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
@@ -120,9 +105,7 @@ bool sol_typenames_init(void)
|
||||
* @param[out] length length of the returned typename
|
||||
* @return typename or \ref NULL in case it wasn't found
|
||||
*/
|
||||
const char *get_struct_field_sol_typename(const uint8_t *field_ptr,
|
||||
uint8_t *const length)
|
||||
{
|
||||
const char *get_struct_field_sol_typename(const uint8_t *field_ptr, uint8_t *const length) {
|
||||
e_type field_type;
|
||||
const uint8_t *typename_ptr;
|
||||
uint8_t typenames_count;
|
||||
@@ -132,25 +115,22 @@ const char *get_struct_field_sol_typename(const uint8_t *field_ptr,
|
||||
field_type = struct_field_type(field_ptr);
|
||||
typename_ptr = get_array_in_mem(sol_typenames, &typenames_count);
|
||||
typename_found = false;
|
||||
while (typenames_count-- > 0)
|
||||
{
|
||||
while (typenames_count-- > 0) {
|
||||
more_type = true;
|
||||
while (more_type)
|
||||
{
|
||||
while (more_type) {
|
||||
more_type = *typename_ptr & TYPENAME_MORE_TYPE;
|
||||
e_type type_enum = *typename_ptr & TYPENAME_ENUM;
|
||||
if (type_enum == field_type)
|
||||
{
|
||||
if (type_enum == field_type) {
|
||||
typename_found = true;
|
||||
}
|
||||
typename_ptr += 1;
|
||||
}
|
||||
typename_ptr = (uint8_t*)get_string_in_mem(typename_ptr, length);
|
||||
if (typename_found) return (char*)typename_ptr;
|
||||
typename_ptr = (uint8_t *) get_string_in_mem(typename_ptr, length);
|
||||
if (typename_found) return (char *) typename_ptr;
|
||||
typename_ptr += *length;
|
||||
}
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return NULL; // Not found
|
||||
return NULL; // Not found
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
|
||||
bool sol_typenames_init(void);
|
||||
|
||||
const char *get_struct_field_sol_typename(const uint8_t *ptr,
|
||||
uint8_t *const length);
|
||||
const char *get_struct_field_sol_typename(const uint8_t *ptr, uint8_t *const length);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // SOL_TYPENAMES_H_
|
||||
#endif // SOL_TYPENAMES_H_
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
#include "mem_utils.h"
|
||||
#include "type_hash.h"
|
||||
#include "shared_context.h"
|
||||
#include "ethUtils.h" // KECCAK256_HASH_BYTESIZE
|
||||
#include "ethUtils.h" // KECCAK256_HASH_BYTESIZE
|
||||
#include "format_hash_field_type.h"
|
||||
#include "hash_bytes.h"
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "typed_data.h"
|
||||
|
||||
/**
|
||||
@@ -19,21 +19,19 @@
|
||||
* @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 *const field_ptr)
|
||||
{
|
||||
static bool encode_and_hash_field(const void *const field_ptr) {
|
||||
const char *name;
|
||||
uint8_t length;
|
||||
|
||||
if (!format_hash_field_type(field_ptr, (cx_hash_t*)&global_sha3))
|
||||
{
|
||||
if (!format_hash_field_type(field_ptr, (cx_hash_t *) &global_sha3)) {
|
||||
return false;
|
||||
}
|
||||
// space between field type name and field name
|
||||
hash_byte(' ', (cx_hash_t*)&global_sha3);
|
||||
hash_byte(' ', (cx_hash_t *) &global_sha3);
|
||||
|
||||
// field name
|
||||
name = get_struct_field_keyname(field_ptr, &length);
|
||||
hash_nbytes((uint8_t*)name, length, (cx_hash_t*)&global_sha3);
|
||||
hash_nbytes((uint8_t *) name, length, (cx_hash_t *) &global_sha3);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -44,8 +42,7 @@ static bool encode_and_hash_field(const void *const 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 void *const struct_ptr)
|
||||
{
|
||||
static bool encode_and_hash_type(const void *const struct_ptr) {
|
||||
const char *struct_name;
|
||||
uint8_t struct_name_length;
|
||||
const uint8_t *field_ptr;
|
||||
@@ -53,29 +50,26 @@ static bool encode_and_hash_type(const void *const struct_ptr)
|
||||
|
||||
// struct name
|
||||
struct_name = get_struct_name(struct_ptr, &struct_name_length);
|
||||
hash_nbytes((uint8_t*)struct_name, struct_name_length, (cx_hash_t*)&global_sha3);
|
||||
hash_nbytes((uint8_t *) struct_name, struct_name_length, (cx_hash_t *) &global_sha3);
|
||||
|
||||
// opening struct parenthese
|
||||
hash_byte('(', (cx_hash_t*)&global_sha3);
|
||||
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)
|
||||
{
|
||||
for (uint8_t idx = 0; idx < fields_count; ++idx) {
|
||||
// comma separating struct fields
|
||||
if (idx > 0)
|
||||
{
|
||||
hash_byte(',', (cx_hash_t*)&global_sha3);
|
||||
if (idx > 0) {
|
||||
hash_byte(',', (cx_hash_t *) &global_sha3);
|
||||
}
|
||||
|
||||
if (encode_and_hash_field(field_ptr) == false)
|
||||
{
|
||||
if (encode_and_hash_field(field_ptr) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
field_ptr = get_next_struct_field(field_ptr);
|
||||
}
|
||||
// closing struct parenthese
|
||||
hash_byte(')', (cx_hash_t*)&global_sha3);
|
||||
hash_byte(')', (cx_hash_t *) &global_sha3);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -86,26 +80,21 @@ static bool encode_and_hash_type(const void *const struct_ptr)
|
||||
* @param[in] deps_count count of how many struct dependencies pointers
|
||||
* @param[in,out] deps pointer to the first dependency pointer
|
||||
*/
|
||||
static void sort_dependencies(uint8_t deps_count,
|
||||
const void **deps)
|
||||
{
|
||||
static void sort_dependencies(uint8_t deps_count, const void **deps) {
|
||||
bool changed;
|
||||
const void *tmp_ptr;
|
||||
const char *name1, *name2;
|
||||
uint8_t namelen1, namelen2;
|
||||
int str_cmp_result;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
changed = false;
|
||||
for (size_t idx = 0; (idx + 1) < deps_count; ++idx)
|
||||
{
|
||||
for (size_t idx = 0; (idx + 1) < deps_count; ++idx) {
|
||||
name1 = get_struct_name(*(deps + idx), &namelen1);
|
||||
name2 = get_struct_name(*(deps + idx + 1), &namelen2);
|
||||
|
||||
str_cmp_result = strncmp(name1, name2, MIN(namelen1, namelen2));
|
||||
if ((str_cmp_result > 0) || ((str_cmp_result == 0) && (namelen1 > namelen2)))
|
||||
{
|
||||
if ((str_cmp_result > 0) || ((str_cmp_result == 0) && (namelen1 > namelen2))) {
|
||||
tmp_ptr = *(deps + idx);
|
||||
*(deps + idx) = *(deps + idx + 1);
|
||||
*(deps + idx + 1) = tmp_ptr;
|
||||
@@ -113,8 +102,7 @@ static void sort_dependencies(uint8_t deps_count,
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (changed);
|
||||
} while (changed);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,8 +115,7 @@ static void sort_dependencies(uint8_t deps_count,
|
||||
*/
|
||||
static const void **get_struct_dependencies(uint8_t *const deps_count,
|
||||
const void **first_dep,
|
||||
const void *const struct_ptr)
|
||||
{
|
||||
const void *const struct_ptr) {
|
||||
uint8_t fields_count;
|
||||
const void *field_ptr;
|
||||
const char *arg_structname;
|
||||
@@ -138,35 +125,28 @@ static const void **get_struct_dependencies(uint8_t *const deps_count,
|
||||
const void **new_dep;
|
||||
|
||||
field_ptr = get_struct_fields_array(struct_ptr, &fields_count);
|
||||
for (uint8_t idx = 0; idx < fields_count; ++idx)
|
||||
{
|
||||
if (struct_field_type(field_ptr) == TYPE_CUSTOM)
|
||||
{
|
||||
for (uint8_t idx = 0; idx < fields_count; ++idx) {
|
||||
if (struct_field_type(field_ptr) == TYPE_CUSTOM) {
|
||||
// get struct name
|
||||
arg_structname = get_struct_field_typename(field_ptr, &arg_structname_length);
|
||||
// from its name, get the pointer to its definition
|
||||
arg_struct_ptr = get_structn(arg_structname, arg_structname_length);
|
||||
|
||||
// check if it is not already present in the dependencies array
|
||||
for (dep_idx = 0; dep_idx < *deps_count; ++dep_idx)
|
||||
{
|
||||
for (dep_idx = 0; dep_idx < *deps_count; ++dep_idx) {
|
||||
// it's a match!
|
||||
if (*(first_dep + dep_idx) == arg_struct_ptr)
|
||||
{
|
||||
if (*(first_dep + dep_idx) == arg_struct_ptr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if it's not present in the array, add it and recurse into it
|
||||
if (dep_idx == *deps_count)
|
||||
{
|
||||
if (dep_idx == *deps_count) {
|
||||
*deps_count += 1;
|
||||
if ((new_dep = MEM_ALLOC_AND_ALIGN_TYPE(void*)) == NULL)
|
||||
{
|
||||
if ((new_dep = MEM_ALLOC_AND_ALIGN_TYPE(void *)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
if (*deps_count == 1)
|
||||
{
|
||||
if (*deps_count == 1) {
|
||||
first_dep = new_dep;
|
||||
}
|
||||
*new_dep = arg_struct_ptr;
|
||||
@@ -187,32 +167,24 @@ static const void **get_struct_dependencies(uint8_t *const deps_count,
|
||||
* @param[in] with_deps if hashed typestring should include struct dependencies
|
||||
* @return pointer to encoded string or \ref NULL in case of a memory allocation error
|
||||
*/
|
||||
bool type_hash(const char *const struct_name,
|
||||
const uint8_t struct_name_length,
|
||||
uint8_t *hash_buf)
|
||||
{
|
||||
const void *const struct_ptr = get_structn(struct_name,
|
||||
struct_name_length);
|
||||
bool type_hash(const char *const struct_name, const uint8_t struct_name_length, uint8_t *hash_buf) {
|
||||
const void *const struct_ptr = get_structn(struct_name, struct_name_length);
|
||||
uint8_t deps_count = 0;
|
||||
const void **deps;
|
||||
void *mem_loc_bak = mem_alloc(0);
|
||||
|
||||
cx_keccak_init(&global_sha3, 256); // init hash
|
||||
cx_keccak_init(&global_sha3, 256); // init hash
|
||||
deps = get_struct_dependencies(&deps_count, NULL, struct_ptr);
|
||||
if ((deps_count > 0) && (deps == NULL))
|
||||
{
|
||||
if ((deps_count > 0) && (deps == NULL)) {
|
||||
return false;
|
||||
}
|
||||
sort_dependencies(deps_count, deps);
|
||||
if (encode_and_hash_type(struct_ptr) == false)
|
||||
{
|
||||
if (encode_and_hash_type(struct_ptr) == false) {
|
||||
return false;
|
||||
}
|
||||
// loop over each struct and generate string
|
||||
for (int idx = 0; idx < deps_count; ++idx)
|
||||
{
|
||||
if (encode_and_hash_type(*deps) == false)
|
||||
{
|
||||
for (int idx = 0; idx < deps_count; ++idx) {
|
||||
if (encode_and_hash_type(*deps) == false) {
|
||||
return false;
|
||||
}
|
||||
deps += 1;
|
||||
@@ -220,13 +192,8 @@ bool type_hash(const char *const struct_name,
|
||||
mem_dealloc(mem_alloc(0) - mem_loc_bak);
|
||||
|
||||
// copy hash into memory
|
||||
cx_hash((cx_hash_t*)&global_sha3,
|
||||
CX_LAST,
|
||||
NULL,
|
||||
0,
|
||||
hash_buf,
|
||||
KECCAK256_HASH_BYTESIZE);
|
||||
cx_hash((cx_hash_t *) &global_sha3, CX_LAST, NULL, 0, hash_buf, KECCAK256_HASH_BYTESIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool type_hash(const char *const struct_name,
|
||||
const uint8_t struct_name_length,
|
||||
uint8_t *hash_buf);
|
||||
bool type_hash(const char *const struct_name, const uint8_t struct_name_length, uint8_t *hash_buf);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // TYPE_HASH_H_
|
||||
#endif // TYPE_HASH_H_
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <string.h>
|
||||
#include "typed_data.h"
|
||||
#include "sol_typenames.h"
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "context.h"
|
||||
#include "mem.h"
|
||||
#include "mem_utils.h"
|
||||
@@ -16,18 +16,14 @@ static s_typed_data *typed_data = NULL;
|
||||
*
|
||||
* @return whether the memory allocation was successful
|
||||
*/
|
||||
bool typed_data_init(void)
|
||||
{
|
||||
if (typed_data == NULL)
|
||||
{
|
||||
if ((typed_data = MEM_ALLOC_AND_ALIGN_TYPE(*typed_data)) == NULL)
|
||||
{
|
||||
bool typed_data_init(void) {
|
||||
if (typed_data == NULL) {
|
||||
if ((typed_data = MEM_ALLOC_AND_ALIGN_TYPE(*typed_data)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
// set types pointer
|
||||
if ((typed_data->structs_array = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if ((typed_data->structs_array = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
@@ -38,8 +34,7 @@ bool typed_data_init(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
void typed_data_deinit(void)
|
||||
{
|
||||
void typed_data_deinit(void) {
|
||||
typed_data = NULL;
|
||||
}
|
||||
|
||||
@@ -50,10 +45,8 @@ void typed_data_deinit(void)
|
||||
* @param[in] ptr pointer to the current location within the struct field
|
||||
* @return pointer to the data right after
|
||||
*/
|
||||
static const uint8_t *field_skip_typedesc(const uint8_t *field_ptr,
|
||||
const uint8_t *ptr)
|
||||
{
|
||||
(void)ptr;
|
||||
static const uint8_t *field_skip_typedesc(const uint8_t *field_ptr, const uint8_t *ptr) {
|
||||
(void) ptr;
|
||||
return field_ptr + sizeof(typedesc_t);
|
||||
}
|
||||
|
||||
@@ -64,13 +57,10 @@ static const uint8_t *field_skip_typedesc(const uint8_t *field_ptr,
|
||||
* @param[in] ptr pointer to the current location within the struct field
|
||||
* @return pointer to the data right after
|
||||
*/
|
||||
static const uint8_t *field_skip_typename(const uint8_t *field_ptr,
|
||||
const uint8_t *ptr)
|
||||
{
|
||||
static const uint8_t *field_skip_typename(const uint8_t *field_ptr, const uint8_t *ptr) {
|
||||
uint8_t size;
|
||||
|
||||
if (struct_field_type(field_ptr) == TYPE_CUSTOM)
|
||||
{
|
||||
if (struct_field_type(field_ptr) == TYPE_CUSTOM) {
|
||||
get_string_in_mem(ptr, &size);
|
||||
ptr += (sizeof(size) + size);
|
||||
}
|
||||
@@ -84,11 +74,8 @@ static const uint8_t *field_skip_typename(const uint8_t *field_ptr,
|
||||
* @param[in] ptr pointer to the current location within the struct field
|
||||
* @return pointer to the data right after
|
||||
*/
|
||||
static const uint8_t *field_skip_typesize(const uint8_t *field_ptr,
|
||||
const uint8_t *ptr)
|
||||
{
|
||||
if (struct_field_has_typesize(field_ptr))
|
||||
{
|
||||
static const uint8_t *field_skip_typesize(const uint8_t *field_ptr, const uint8_t *ptr) {
|
||||
if (struct_field_has_typesize(field_ptr)) {
|
||||
ptr += sizeof(typesize_t);
|
||||
}
|
||||
return ptr;
|
||||
@@ -101,16 +88,12 @@ static const uint8_t *field_skip_typesize(const uint8_t *field_ptr,
|
||||
* @param[in] ptr pointer to the current location within the struct field
|
||||
* @return pointer to the data right after
|
||||
*/
|
||||
static const uint8_t *field_skip_array_levels(const uint8_t *field_ptr,
|
||||
const uint8_t *ptr)
|
||||
{
|
||||
static const uint8_t *field_skip_array_levels(const uint8_t *field_ptr, const uint8_t *ptr) {
|
||||
uint8_t size;
|
||||
|
||||
if (struct_field_is_array(field_ptr))
|
||||
{
|
||||
if (struct_field_is_array(field_ptr)) {
|
||||
ptr = get_array_in_mem(ptr, &size);
|
||||
while (size-- > 0)
|
||||
{
|
||||
while (size-- > 0) {
|
||||
ptr = get_next_struct_field_array_lvl(ptr);
|
||||
}
|
||||
}
|
||||
@@ -124,12 +107,10 @@ static const uint8_t *field_skip_array_levels(const uint8_t *field_ptr,
|
||||
* @param[in] ptr pointer to the current location within the struct field
|
||||
* @return pointer to the data right after
|
||||
*/
|
||||
static const uint8_t *field_skip_keyname(const uint8_t *field_ptr,
|
||||
const uint8_t *ptr)
|
||||
{
|
||||
static const uint8_t *field_skip_keyname(const uint8_t *field_ptr, const uint8_t *ptr) {
|
||||
uint8_t size;
|
||||
|
||||
(void)field_ptr;
|
||||
(void) field_ptr;
|
||||
ptr = get_array_in_mem(ptr, &size);
|
||||
return ptr + size;
|
||||
}
|
||||
@@ -141,15 +122,12 @@ static const uint8_t *field_skip_keyname(const uint8_t *field_ptr,
|
||||
* @param[out] array_size pointer to array size
|
||||
* @return pointer to data
|
||||
*/
|
||||
const void *get_array_in_mem(const void *ptr, uint8_t *const array_size)
|
||||
{
|
||||
if (ptr == NULL)
|
||||
{
|
||||
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;
|
||||
if (array_size) {
|
||||
*array_size = *(uint8_t *) ptr;
|
||||
}
|
||||
return (ptr + sizeof(*array_size));
|
||||
}
|
||||
@@ -161,9 +139,8 @@ const void *get_array_in_mem(const void *ptr, uint8_t *const array_size)
|
||||
* @param[out] string_length pointer to string length
|
||||
* @return pointer to beginning of the string
|
||||
*/
|
||||
const char *get_string_in_mem(const uint8_t *ptr, uint8_t *const string_length)
|
||||
{
|
||||
return (char*)get_array_in_mem(ptr, string_length);
|
||||
const char *get_string_in_mem(const uint8_t *ptr, uint8_t *const string_length) {
|
||||
return (char *) get_array_in_mem(ptr, string_length);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,10 +149,8 @@ const char *get_string_in_mem(const uint8_t *ptr, uint8_t *const string_length)
|
||||
* @param[in] field_ptr struct field pointer
|
||||
* @return TypeDesc
|
||||
*/
|
||||
static inline typedesc_t get_struct_field_typedesc(const uint8_t *const field_ptr)
|
||||
{
|
||||
if (field_ptr == NULL)
|
||||
{
|
||||
static inline typedesc_t get_struct_field_typedesc(const uint8_t *const field_ptr) {
|
||||
if (field_ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return *field_ptr;
|
||||
@@ -187,8 +162,7 @@ static inline typedesc_t get_struct_field_typedesc(const uint8_t *const field_pt
|
||||
* @param[in] field_ptr struct field pointer
|
||||
* @return bool whether it is the case
|
||||
*/
|
||||
bool struct_field_is_array(const uint8_t *const field_ptr)
|
||||
{
|
||||
bool struct_field_is_array(const uint8_t *const field_ptr) {
|
||||
return (get_struct_field_typedesc(field_ptr) & ARRAY_MASK);
|
||||
}
|
||||
|
||||
@@ -198,8 +172,7 @@ bool struct_field_is_array(const uint8_t *const field_ptr)
|
||||
* @param[in] field_ptr struct field pointer
|
||||
* @return bool whether it is the case
|
||||
*/
|
||||
bool struct_field_has_typesize(const uint8_t *const field_ptr)
|
||||
{
|
||||
bool struct_field_has_typesize(const uint8_t *const field_ptr) {
|
||||
return (get_struct_field_typedesc(field_ptr) & TYPESIZE_MASK);
|
||||
}
|
||||
|
||||
@@ -209,8 +182,7 @@ bool struct_field_has_typesize(const uint8_t *const field_ptr)
|
||||
* @param[in] field_ptr struct field pointer
|
||||
* @return its type enum
|
||||
*/
|
||||
e_type struct_field_type(const uint8_t *const field_ptr)
|
||||
{
|
||||
e_type struct_field_type(const uint8_t *const field_ptr) {
|
||||
return (get_struct_field_typedesc(field_ptr) & TYPE_MASK);
|
||||
}
|
||||
|
||||
@@ -220,10 +192,8 @@ e_type struct_field_type(const uint8_t *const field_ptr)
|
||||
* @param[in] field_ptr struct field pointer
|
||||
* @return its type size
|
||||
*/
|
||||
uint8_t get_struct_field_typesize(const uint8_t *const field_ptr)
|
||||
{
|
||||
if (field_ptr == NULL)
|
||||
{
|
||||
uint8_t get_struct_field_typesize(const uint8_t *const field_ptr) {
|
||||
if (field_ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return *field_skip_typedesc(field_ptr, NULL);
|
||||
@@ -236,13 +206,10 @@ uint8_t get_struct_field_typesize(const uint8_t *const field_ptr)
|
||||
* @param[out] length the type name length
|
||||
* @return type name pointer
|
||||
*/
|
||||
const char *get_struct_field_custom_typename(const uint8_t *field_ptr,
|
||||
uint8_t *const length)
|
||||
{
|
||||
const char *get_struct_field_custom_typename(const uint8_t *field_ptr, uint8_t *const length) {
|
||||
const uint8_t *ptr;
|
||||
|
||||
if (field_ptr == NULL)
|
||||
{
|
||||
if (field_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = field_skip_typedesc(field_ptr, NULL);
|
||||
@@ -256,15 +223,11 @@ const char *get_struct_field_custom_typename(const uint8_t *field_ptr,
|
||||
* @param[out] length the type name length
|
||||
* @return type name pointer
|
||||
*/
|
||||
const char *get_struct_field_typename(const uint8_t *field_ptr,
|
||||
uint8_t *const length)
|
||||
{
|
||||
if (field_ptr == NULL)
|
||||
{
|
||||
const char *get_struct_field_typename(const uint8_t *field_ptr, uint8_t *const length) {
|
||||
if (field_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (struct_field_type(field_ptr) == TYPE_CUSTOM)
|
||||
{
|
||||
if (struct_field_type(field_ptr) == TYPE_CUSTOM) {
|
||||
return get_struct_field_custom_typename(field_ptr, length);
|
||||
}
|
||||
return get_struct_field_sol_typename(field_ptr, length);
|
||||
@@ -277,17 +240,12 @@ const char *get_struct_field_typename(const uint8_t *field_ptr,
|
||||
* @param[out] array_size pointer to array size
|
||||
* @return array type of that depth
|
||||
*/
|
||||
e_array_type struct_field_array_depth(const uint8_t *array_depth_ptr,
|
||||
uint8_t *const array_size)
|
||||
{
|
||||
if (array_depth_ptr == NULL)
|
||||
{
|
||||
e_array_type struct_field_array_depth(const uint8_t *array_depth_ptr, uint8_t *const array_size) {
|
||||
if (array_depth_ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (*array_depth_ptr == ARRAY_FIXED_SIZE)
|
||||
{
|
||||
if (array_size != NULL)
|
||||
{
|
||||
if (*array_depth_ptr == ARRAY_FIXED_SIZE) {
|
||||
if (array_size != NULL) {
|
||||
*array_size = *(array_depth_ptr + sizeof(uint8_t));
|
||||
}
|
||||
}
|
||||
@@ -300,16 +258,13 @@ e_array_type struct_field_array_depth(const uint8_t *array_depth_ptr,
|
||||
* @param[in] array_depth_ptr given array depth
|
||||
* @return next array depth
|
||||
*/
|
||||
const uint8_t *get_next_struct_field_array_lvl(const uint8_t *const array_depth_ptr)
|
||||
{
|
||||
const uint8_t *get_next_struct_field_array_lvl(const uint8_t *const array_depth_ptr) {
|
||||
const uint8_t *ptr;
|
||||
|
||||
if (array_depth_ptr == NULL)
|
||||
{
|
||||
if (array_depth_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
switch (*array_depth_ptr)
|
||||
{
|
||||
switch (*array_depth_ptr) {
|
||||
case ARRAY_DYNAMIC:
|
||||
ptr = array_depth_ptr;
|
||||
break;
|
||||
@@ -332,12 +287,10 @@ const uint8_t *get_next_struct_field_array_lvl(const uint8_t *const array_depth_
|
||||
* @return pointer to the first array level
|
||||
*/
|
||||
const uint8_t *get_struct_field_array_lvls_array(const uint8_t *const field_ptr,
|
||||
uint8_t *const length)
|
||||
{
|
||||
uint8_t *const length) {
|
||||
const uint8_t *ptr;
|
||||
|
||||
if (field_ptr == NULL)
|
||||
{
|
||||
if (field_ptr == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return NULL;
|
||||
}
|
||||
@@ -354,13 +307,10 @@ const uint8_t *get_struct_field_array_lvls_array(const uint8_t *const field_ptr,
|
||||
* @param[out] length name length
|
||||
* @return key name
|
||||
*/
|
||||
const char *get_struct_field_keyname(const uint8_t *field_ptr,
|
||||
uint8_t *const length)
|
||||
{
|
||||
const char *get_struct_field_keyname(const uint8_t *field_ptr, uint8_t *const length) {
|
||||
const uint8_t *ptr;
|
||||
|
||||
if (field_ptr == NULL)
|
||||
{
|
||||
if (field_ptr == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return NULL;
|
||||
}
|
||||
@@ -377,12 +327,10 @@ const char *get_struct_field_keyname(const uint8_t *field_ptr,
|
||||
* @param[in] field_ptr given struct field
|
||||
* @return pointer to the next field
|
||||
*/
|
||||
const uint8_t *get_next_struct_field(const void *const field_ptr)
|
||||
{
|
||||
const uint8_t *get_next_struct_field(const void *const field_ptr) {
|
||||
const void *ptr;
|
||||
|
||||
if (field_ptr == NULL)
|
||||
{
|
||||
if (field_ptr == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return NULL;
|
||||
}
|
||||
@@ -400,14 +348,12 @@ const uint8_t *get_next_struct_field(const void *const field_ptr)
|
||||
* @param[out] length name length
|
||||
* @return struct name
|
||||
*/
|
||||
const char *get_struct_name(const uint8_t *const struct_ptr, uint8_t *const length)
|
||||
{
|
||||
if (struct_ptr == NULL)
|
||||
{
|
||||
const char *get_struct_name(const uint8_t *const struct_ptr, uint8_t *const length) {
|
||||
if (struct_ptr == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return NULL;
|
||||
}
|
||||
return (char*)get_string_in_mem(struct_ptr, length);
|
||||
return (char *) get_string_in_mem(struct_ptr, length);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,20 +363,17 @@ const char *get_struct_name(const uint8_t *const struct_ptr, uint8_t *const leng
|
||||
* @param[out] length name length
|
||||
* @return struct name
|
||||
*/
|
||||
const uint8_t *get_struct_fields_array(const uint8_t *const struct_ptr,
|
||||
uint8_t *const length)
|
||||
{
|
||||
const uint8_t *get_struct_fields_array(const uint8_t *const struct_ptr, uint8_t *const length) {
|
||||
const void *ptr;
|
||||
uint8_t name_length;
|
||||
|
||||
if (struct_ptr == NULL)
|
||||
{
|
||||
if (struct_ptr == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return NULL;
|
||||
}
|
||||
ptr = struct_ptr;
|
||||
get_struct_name(struct_ptr, &name_length);
|
||||
ptr += (sizeof(name_length) + name_length); // skip length
|
||||
ptr += (sizeof(name_length) + name_length); // skip length
|
||||
return get_array_in_mem(ptr, length);
|
||||
}
|
||||
|
||||
@@ -440,19 +383,16 @@ const uint8_t *get_struct_fields_array(const uint8_t *const struct_ptr,
|
||||
* @param[in] struct_ptr given struct
|
||||
* @return pointer to next struct
|
||||
*/
|
||||
const uint8_t *get_next_struct(const uint8_t *const struct_ptr)
|
||||
{
|
||||
const uint8_t *get_next_struct(const uint8_t *const struct_ptr) {
|
||||
uint8_t fields_count;
|
||||
const void *ptr;
|
||||
|
||||
if (struct_ptr == NULL)
|
||||
{
|
||||
if (struct_ptr == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return NULL;
|
||||
}
|
||||
ptr = get_struct_fields_array(struct_ptr, &fields_count);
|
||||
while (fields_count-- > 0)
|
||||
{
|
||||
while (fields_count-- > 0) {
|
||||
ptr = get_next_struct_field(ptr);
|
||||
}
|
||||
return ptr;
|
||||
@@ -464,8 +404,7 @@ const uint8_t *get_next_struct(const uint8_t *const struct_ptr)
|
||||
* @param[out] length number of structs
|
||||
* @return pointer to the first struct
|
||||
*/
|
||||
const uint8_t *get_structs_array(uint8_t *const length)
|
||||
{
|
||||
const uint8_t *get_structs_array(uint8_t *const length) {
|
||||
return get_array_in_mem(typed_data->structs_array, length);
|
||||
}
|
||||
|
||||
@@ -476,25 +415,20 @@ const uint8_t *get_structs_array(uint8_t *const length)
|
||||
* @param[in] length name length
|
||||
* @return pointer to struct
|
||||
*/
|
||||
const uint8_t *get_structn(const char *const name,
|
||||
const uint8_t length)
|
||||
{
|
||||
const uint8_t *get_structn(const char *const name, const uint8_t length) {
|
||||
uint8_t structs_count;
|
||||
const uint8_t *struct_ptr;
|
||||
const char *struct_name;
|
||||
uint8_t name_length;
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
if (name == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return NULL;
|
||||
}
|
||||
struct_ptr = get_structs_array(&structs_count);
|
||||
while (structs_count-- > 0)
|
||||
{
|
||||
while (structs_count-- > 0) {
|
||||
struct_name = get_struct_name(struct_ptr, &name_length);
|
||||
if ((length == name_length) && (memcmp(name, struct_name, length) == 0))
|
||||
{
|
||||
if ((length == name_length) && (memcmp(name, struct_name, length) == 0)) {
|
||||
return struct_ptr;
|
||||
}
|
||||
struct_ptr = get_next_struct(struct_ptr);
|
||||
@@ -510,13 +444,11 @@ const uint8_t *get_structn(const char *const name,
|
||||
* @param[in] name name
|
||||
* @return whether it was successful
|
||||
*/
|
||||
bool set_struct_name(uint8_t length, const uint8_t *const name)
|
||||
{
|
||||
bool set_struct_name(uint8_t length, const uint8_t *const name) {
|
||||
uint8_t *length_ptr;
|
||||
char *name_ptr;
|
||||
|
||||
if ((name == NULL) || (typed_data == NULL))
|
||||
{
|
||||
if ((name == NULL) || (typed_data == NULL)) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
@@ -524,24 +456,21 @@ bool set_struct_name(uint8_t length, const uint8_t *const name)
|
||||
*(typed_data->structs_array) += 1;
|
||||
|
||||
// copy length
|
||||
if ((length_ptr = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if ((length_ptr = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
*length_ptr = length;
|
||||
|
||||
// copy name
|
||||
if ((name_ptr = mem_alloc(sizeof(char) * length)) == NULL)
|
||||
{
|
||||
if ((name_ptr = mem_alloc(sizeof(char) * length)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
memmove(name_ptr, name, length);
|
||||
|
||||
// initialize number of fields
|
||||
if ((typed_data->current_struct_fields_array = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if ((typed_data->current_struct_fields_array = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
@@ -558,18 +487,16 @@ bool set_struct_name(uint8_t length, const uint8_t *const name)
|
||||
*/
|
||||
static const typedesc_t *set_struct_field_typedesc(const uint8_t *const data,
|
||||
uint8_t *data_idx,
|
||||
uint8_t length)
|
||||
{
|
||||
uint8_t length) {
|
||||
typedesc_t *typedesc_ptr;
|
||||
|
||||
// copy TypeDesc
|
||||
if ((*data_idx + sizeof(*typedesc_ptr)) > length) // check buffer bound
|
||||
if ((*data_idx + sizeof(*typedesc_ptr)) > length) // check buffer bound
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if ((typedesc_ptr = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if ((typedesc_ptr = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
@@ -586,32 +513,29 @@ static const typedesc_t *set_struct_field_typedesc(const uint8_t *const data,
|
||||
*/
|
||||
static bool set_struct_field_custom_typename(const uint8_t *const data,
|
||||
uint8_t *data_idx,
|
||||
uint8_t length)
|
||||
{
|
||||
uint8_t length) {
|
||||
uint8_t *typename_len_ptr;
|
||||
char *typename;
|
||||
|
||||
// copy custom struct name length
|
||||
if ((*data_idx + sizeof(*typename_len_ptr)) > length) // check buffer bound
|
||||
if ((*data_idx + sizeof(*typename_len_ptr)) > length) // check buffer bound
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if ((typename_len_ptr = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
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 ((*data_idx + *typename_len_ptr) > length) // check buffer bound
|
||||
if ((*data_idx + *typename_len_ptr) > length) // check buffer bound
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if ((typename = mem_alloc(sizeof(char) * *typename_len_ptr)) == NULL)
|
||||
{
|
||||
if ((typename = mem_alloc(sizeof(char) * *typename_len_ptr)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
@@ -627,55 +551,46 @@ static bool set_struct_field_custom_typename(const uint8_t *const data,
|
||||
* @param[in] data_idx the data index
|
||||
* @return whether it was successful
|
||||
*/
|
||||
static bool set_struct_field_array(const uint8_t *const data,
|
||||
uint8_t *data_idx,
|
||||
uint8_t length)
|
||||
{
|
||||
static bool set_struct_field_array(const uint8_t *const data, uint8_t *data_idx, uint8_t length) {
|
||||
uint8_t *array_levels_count;
|
||||
e_array_type *array_level;
|
||||
uint8_t *array_level_size;
|
||||
|
||||
if ((*data_idx + sizeof(*array_levels_count)) > length) // check buffer bound
|
||||
if ((*data_idx + sizeof(*array_levels_count)) > length) // check buffer bound
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if ((array_levels_count = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
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 ((*data_idx + sizeof(*array_level)) > length) // check buffer bound
|
||||
for (int idx = 0; idx < *array_levels_count; ++idx) {
|
||||
if ((*data_idx + sizeof(*array_level)) > length) // check buffer bound
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if ((array_level = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if ((array_level = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
*array_level = data[(*data_idx)++];
|
||||
if (*array_level > ARRAY_TYPES_COUNT)
|
||||
{
|
||||
if (*array_level > ARRAY_TYPES_COUNT) {
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
switch (*array_level)
|
||||
{
|
||||
case ARRAY_DYNAMIC: // nothing to do
|
||||
switch (*array_level) {
|
||||
case ARRAY_DYNAMIC: // nothing to do
|
||||
break;
|
||||
case ARRAY_FIXED_SIZE:
|
||||
if ((*data_idx + sizeof(*array_level_size)) > length) // check buffer bound
|
||||
if ((*data_idx + sizeof(*array_level_size)) > length) // check buffer bound
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if ((array_level_size = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if ((array_level_size = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
@@ -699,18 +614,16 @@ static bool set_struct_field_array(const uint8_t *const data,
|
||||
*/
|
||||
static bool set_struct_field_typesize(const uint8_t *const data,
|
||||
uint8_t *data_idx,
|
||||
uint8_t length)
|
||||
{
|
||||
uint8_t length) {
|
||||
uint8_t *typesize_ptr;
|
||||
|
||||
// copy TypeSize
|
||||
if ((*data_idx + sizeof(*typesize_ptr)) > length) // check buffer bound
|
||||
if ((*data_idx + sizeof(*typesize_ptr)) > length) // check buffer bound
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if ((typesize_ptr = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if ((typesize_ptr = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
@@ -725,34 +638,29 @@ static bool set_struct_field_typesize(const uint8_t *const data,
|
||||
* @param[in,out] data_idx the data index
|
||||
* @return whether it was successful
|
||||
*/
|
||||
static bool set_struct_field_keyname(const uint8_t *const data,
|
||||
uint8_t *data_idx,
|
||||
uint8_t length)
|
||||
{
|
||||
static bool set_struct_field_keyname(const uint8_t *const data, uint8_t *data_idx, uint8_t length) {
|
||||
uint8_t *keyname_len_ptr;
|
||||
char *keyname_ptr;
|
||||
|
||||
// copy length
|
||||
if ((*data_idx + sizeof(*keyname_len_ptr)) > length) // check buffer bound
|
||||
if ((*data_idx + sizeof(*keyname_len_ptr)) > length) // check buffer bound
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if ((keyname_len_ptr = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
if ((keyname_len_ptr = mem_alloc(sizeof(uint8_t))) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
*keyname_len_ptr = data[(*data_idx)++];
|
||||
|
||||
// copy name
|
||||
if ((*data_idx + *keyname_len_ptr) > length) // check buffer bound
|
||||
if ((*data_idx + *keyname_len_ptr) > length) // check buffer bound
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if ((keyname_ptr = mem_alloc(sizeof(char) * *keyname_len_ptr)) == NULL)
|
||||
{
|
||||
if ((keyname_ptr = mem_alloc(sizeof(char) * *keyname_len_ptr)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
return false;
|
||||
}
|
||||
@@ -768,58 +676,45 @@ static bool set_struct_field_keyname(const uint8_t *const data,
|
||||
* @param[in] data the field data
|
||||
* @return whether it was successful
|
||||
*/
|
||||
bool set_struct_field(uint8_t length, const uint8_t *const data)
|
||||
{
|
||||
bool set_struct_field(uint8_t length, const uint8_t *const data) {
|
||||
const typedesc_t *typedesc_ptr;
|
||||
uint8_t data_idx = 0;
|
||||
|
||||
if ((data == NULL) || (length == 0))
|
||||
{
|
||||
if ((data == NULL) || (length == 0)) {
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
else if (typed_data == NULL)
|
||||
{
|
||||
} else if (typed_data == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
// increment number of struct fields
|
||||
*(typed_data->current_struct_fields_array) += 1;
|
||||
|
||||
if ((typedesc_ptr = set_struct_field_typedesc(data, &data_idx, length)) == NULL)
|
||||
{
|
||||
if ((typedesc_ptr = set_struct_field_typedesc(data, &data_idx, length)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check TypeSize flag in TypeDesc
|
||||
if (*typedesc_ptr & TYPESIZE_MASK)
|
||||
{
|
||||
if (set_struct_field_typesize(data, &data_idx, length) == false)
|
||||
{
|
||||
if (*typedesc_ptr & TYPESIZE_MASK) {
|
||||
if (set_struct_field_typesize(data, &data_idx, length) == false) {
|
||||
return false;
|
||||
}
|
||||
} else if ((*typedesc_ptr & TYPE_MASK) == TYPE_CUSTOM) {
|
||||
if (set_struct_field_custom_typename(data, &data_idx, length) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ((*typedesc_ptr & TYPE_MASK) == TYPE_CUSTOM)
|
||||
{
|
||||
if (set_struct_field_custom_typename(data, &data_idx, length) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (*typedesc_ptr & ARRAY_MASK)
|
||||
{
|
||||
if (set_struct_field_array(data, &data_idx, length) == false)
|
||||
{
|
||||
if (*typedesc_ptr & ARRAY_MASK) {
|
||||
if (set_struct_field_array(data, &data_idx, length) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (set_struct_field_keyname(data, &data_idx, length) == false)
|
||||
{
|
||||
if (set_struct_field_keyname(data, &data_idx, length) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data_idx != length) // check that there is no more
|
||||
if (data_idx != length) // check that there is no more
|
||||
{
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
@@ -827,4 +722,4 @@ bool set_struct_field(uint8_t length, const uint8_t *const data)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -7,21 +7,14 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
// TypeDesc masks
|
||||
#define TYPE_MASK (0xF)
|
||||
#define ARRAY_MASK (1 << 7)
|
||||
#define TYPESIZE_MASK (1 << 6)
|
||||
#define TYPENAME_ENUM (0xF)
|
||||
#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, ARRAY_TYPES_COUNT } e_array_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ARRAY_DYNAMIC = 0,
|
||||
ARRAY_FIXED_SIZE,
|
||||
ARRAY_TYPES_COUNT
|
||||
} e_array_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
// contract defined struct
|
||||
TYPE_CUSTOM = 0,
|
||||
// native types
|
||||
@@ -33,48 +26,40 @@ typedef enum
|
||||
TYPE_SOL_BYTES_FIX,
|
||||
TYPE_SOL_BYTES_DYN,
|
||||
TYPES_COUNT
|
||||
} e_type;
|
||||
} e_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint8_t *structs_array;
|
||||
uint8_t *current_struct_fields_array;
|
||||
} s_typed_data;
|
||||
} s_typed_data;
|
||||
|
||||
typedef uint8_t typedesc_t;
|
||||
typedef uint8_t typesize_t;
|
||||
|
||||
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);
|
||||
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 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 *const ptr);
|
||||
const uint8_t *struct_field_half_skip(const uint8_t *ptr);
|
||||
const uint8_t *get_struct_field_array_lvls_array(const uint8_t *const ptr,
|
||||
uint8_t *const length);
|
||||
const char *get_struct_field_keyname(const uint8_t *ptr,
|
||||
uint8_t *const length);
|
||||
const uint8_t *get_struct_field_array_lvls_array(const uint8_t *const 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_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(uint8_t *const length);
|
||||
const uint8_t *get_structn(const char *const name_ptr,
|
||||
const uint8_t name_length);
|
||||
bool set_struct_name(uint8_t length, const uint8_t *const name);
|
||||
bool set_struct_field(uint8_t length, const uint8_t *const data);
|
||||
bool typed_data_init(void);
|
||||
void typed_data_deinit(void);
|
||||
const uint8_t *get_structn(const char *const name_ptr, const uint8_t name_length);
|
||||
bool set_struct_name(uint8_t length, const uint8_t *const name);
|
||||
bool set_struct_field(uint8_t length, const uint8_t *const data);
|
||||
bool typed_data_init(void);
|
||||
void typed_data_deinit(void);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // TYPED_DATA_H_
|
||||
#endif // TYPED_DATA_H_
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "ui_flow_712.h"
|
||||
#include "ui_logic.h"
|
||||
#include "shared_context.h" // strings
|
||||
#include "shared_context.h" // strings
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
@@ -54,4 +54,4 @@ UX_FLOW(ux_712_flow,
|
||||
&ux_712_step_approve,
|
||||
&ux_712_step_reject);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
|
||||
extern const ux_flow_step_t* const ux_712_flow[];
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // UI_FLOW_712_H_
|
||||
#endif // UI_FLOW_712_H_
|
||||
|
||||
@@ -9,40 +9,33 @@
|
||||
#include "ux_flow_engine.h"
|
||||
#include "ui_flow_712.h"
|
||||
#include "shared_context.h"
|
||||
#include "ethUtils.h" // getEthDisplayableAddress
|
||||
#include "utils.h" // uint256_to_decimal
|
||||
#include "ethUtils.h" // getEthDisplayableAddress
|
||||
#include "utils.h" // uint256_to_decimal
|
||||
#include "common_712.h"
|
||||
#include "context.h" // eip712_context_deinit
|
||||
#include "uint256.h" // tostring256 && tostring256_signed
|
||||
#include "path.h" // path_get_root_type
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "context.h" // eip712_context_deinit
|
||||
#include "uint256.h" // tostring256 && tostring256_signed
|
||||
#include "path.h" // path_get_root_type
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "typed_data.h"
|
||||
#include "commands_712.h"
|
||||
|
||||
|
||||
static t_ui_context *ui_ctx = NULL;
|
||||
|
||||
|
||||
/**
|
||||
* Checks on the UI context to determine if the next EIP 712 field should be shown
|
||||
*
|
||||
* @return whether the next field should be shown
|
||||
*/
|
||||
static bool ui_712_field_shown(void)
|
||||
{
|
||||
static bool ui_712_field_shown(void) {
|
||||
bool ret = false;
|
||||
|
||||
if (ui_ctx->filtering_mode == EIP712_FILTERING_BASIC)
|
||||
{
|
||||
if (N_storage.verbose_eip712 || (path_get_root_type() == ROOT_DOMAIN))
|
||||
{
|
||||
if (ui_ctx->filtering_mode == EIP712_FILTERING_BASIC) {
|
||||
if (N_storage.verbose_eip712 || (path_get_root_type() == ROOT_DOMAIN)) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
else // EIP712_FILTERING_FULL
|
||||
} else // EIP712_FILTERING_FULL
|
||||
{
|
||||
if (ui_ctx->field_flags & UI_712_FIELD_SHOWN)
|
||||
{
|
||||
if (ui_ctx->field_flags & UI_712_FIELD_SHOWN) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
@@ -62,22 +55,17 @@ static void ui_712_set_buf(const char *const src,
|
||||
size_t src_length,
|
||||
char *const dst,
|
||||
size_t dst_length,
|
||||
bool explicit_trunc)
|
||||
{
|
||||
bool explicit_trunc) {
|
||||
uint8_t cpy_length;
|
||||
|
||||
if (src_length < dst_length)
|
||||
{
|
||||
if (src_length < dst_length) {
|
||||
cpy_length = src_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
cpy_length = dst_length - 1;
|
||||
}
|
||||
memcpy(dst, src, cpy_length);
|
||||
dst[cpy_length] = '\0';
|
||||
if (explicit_trunc && (src_length > dst_length))
|
||||
{
|
||||
if (explicit_trunc && (src_length > dst_length)) {
|
||||
memcpy(dst + cpy_length - 3, "...", 3);
|
||||
}
|
||||
}
|
||||
@@ -85,10 +73,8 @@ static void ui_712_set_buf(const char *const src,
|
||||
/**
|
||||
* Skip the field if needed and reset its UI flags
|
||||
*/
|
||||
void ui_712_finalize_field(void)
|
||||
{
|
||||
if (!ui_712_field_shown())
|
||||
{
|
||||
void ui_712_finalize_field(void) {
|
||||
if (!ui_712_field_shown()) {
|
||||
ui_712_next_field();
|
||||
}
|
||||
ui_712_field_flags_reset();
|
||||
@@ -100,8 +86,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 *const str, uint8_t length) {
|
||||
ui_712_set_buf(str, length, strings.tmp.tmp2, sizeof(strings.tmp.tmp2), false);
|
||||
}
|
||||
|
||||
@@ -111,23 +96,19 @@ 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 *const str, uint8_t length) {
|
||||
ui_712_set_buf(str, length, strings.tmp.tmp, sizeof(strings.tmp.tmp), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redraw the dynamic UI step that shows EIP712 information
|
||||
*/
|
||||
void ui_712_redraw_generic_step(void)
|
||||
{
|
||||
if (!ui_ctx->shown) // Initialize if it is not already
|
||||
void ui_712_redraw_generic_step(void) {
|
||||
if (!ui_ctx->shown) // Initialize if it is not already
|
||||
{
|
||||
ux_flow_init(0, ux_712_flow, NULL);
|
||||
ui_ctx->shown = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// not pretty, manually changes the internal state of the UX flow
|
||||
// so that we always land on the first screen of a paging step without any visible
|
||||
// screen glitching (quick screen switching)
|
||||
@@ -141,33 +122,22 @@ void ui_712_redraw_generic_step(void)
|
||||
* Called on the intermediate dummy screen between the dynamic step
|
||||
* && the approve/reject screen
|
||||
*/
|
||||
void ui_712_next_field(void)
|
||||
{
|
||||
if (ui_ctx == NULL)
|
||||
{
|
||||
void ui_712_next_field(void) {
|
||||
if (ui_ctx == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return;
|
||||
}
|
||||
if (ui_ctx->structs_to_review > 0)
|
||||
{
|
||||
if (ui_ctx->structs_to_review > 0) {
|
||||
ui_712_review_struct(path_get_nth_field_to_last(ui_ctx->structs_to_review));
|
||||
ui_ctx->structs_to_review -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ui_ctx->end_reached)
|
||||
{
|
||||
} else {
|
||||
if (!ui_ctx->end_reached) {
|
||||
handle_eip712_return_code(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ui_ctx->pos == UI_712_POS_REVIEW)
|
||||
{
|
||||
} else {
|
||||
if (ui_ctx->pos == UI_712_POS_REVIEW) {
|
||||
ux_flow_next();
|
||||
ui_ctx->pos = UI_712_POS_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ux_flow_prev();
|
||||
ui_ctx->pos = UI_712_POS_REVIEW;
|
||||
}
|
||||
@@ -180,20 +150,17 @@ void 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 *const struct_ptr) {
|
||||
const char *struct_name;
|
||||
uint8_t struct_name_length;
|
||||
const char *const title = "Review struct";
|
||||
|
||||
if (ui_ctx == NULL)
|
||||
{
|
||||
if (ui_ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui_712_set_title(title, strlen(title));
|
||||
if ((struct_name = get_struct_name(struct_ptr, &struct_name_length)) != NULL)
|
||||
{
|
||||
if ((struct_name = get_struct_name(struct_ptr, &struct_name_length)) != NULL) {
|
||||
ui_712_set_value(struct_name, struct_name_length);
|
||||
}
|
||||
ui_712_redraw_generic_step();
|
||||
@@ -202,8 +169,7 @@ 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)
|
||||
{
|
||||
void ui_712_message_hash(void) {
|
||||
const char *const title = "Message hash";
|
||||
|
||||
ui_712_set_title(title, strlen(title));
|
||||
@@ -221,11 +187,9 @@ void ui_712_message_hash(void)
|
||||
* @param[in] data the data that needs formatting
|
||||
* @param[in] length its length
|
||||
*/
|
||||
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 *const data, uint8_t length) {
|
||||
if (ui_712_field_shown()) {
|
||||
ui_712_set_value((char *) data, length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,16 +200,13 @@ static void ui_712_format_str(const uint8_t *const data, uint8_t length)
|
||||
* @param[in] length its length
|
||||
* @return if the formatting was successful
|
||||
*/
|
||||
static bool ui_712_format_addr(const uint8_t *const data, uint8_t length)
|
||||
{
|
||||
if (length != ADDRESS_LENGTH)
|
||||
{
|
||||
static bool ui_712_format_addr(const uint8_t *const data, uint8_t length) {
|
||||
if (length != ADDRESS_LENGTH) {
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if (ui_712_field_shown())
|
||||
{
|
||||
getEthDisplayableAddress((uint8_t*)data,
|
||||
if (ui_712_field_shown()) {
|
||||
getEthDisplayableAddress((uint8_t *) data,
|
||||
strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
&global_sha3,
|
||||
@@ -261,20 +222,17 @@ static bool ui_712_format_addr(const uint8_t *const data, uint8_t length)
|
||||
* @param[in] length its length
|
||||
* @return if the formatting was successful
|
||||
*/
|
||||
static bool ui_712_format_bool(const uint8_t *const data, uint8_t length)
|
||||
{
|
||||
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";
|
||||
const char *str;
|
||||
|
||||
if (length != 1)
|
||||
{
|
||||
if (length != 1) {
|
||||
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
str = *data ? true_str : false_str;
|
||||
if (ui_712_field_shown())
|
||||
{
|
||||
if (ui_712_field_shown()) {
|
||||
ui_712_set_value(str, strlen(str));
|
||||
}
|
||||
return true;
|
||||
@@ -286,19 +244,12 @@ 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
|
||||
*/
|
||||
static void ui_712_format_bytes(const uint8_t *const data, uint8_t length)
|
||||
{
|
||||
if (ui_712_field_shown())
|
||||
{
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"0x%.*H",
|
||||
length,
|
||||
data);
|
||||
static void ui_712_format_bytes(const uint8_t *const data, uint8_t length) {
|
||||
if (ui_712_field_shown()) {
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", length, data);
|
||||
// +2 for the "0x"
|
||||
// x2 for each byte value is represented by 2 ASCII characters
|
||||
if ((2 + (length * 2)) > (sizeof(strings.tmp.tmp) - 1))
|
||||
{
|
||||
if ((2 + (length * 2)) > (sizeof(strings.tmp.tmp) - 1)) {
|
||||
strings.tmp.tmp[sizeof(strings.tmp.tmp) - 1 - 3] = '\0';
|
||||
strcat(strings.tmp.tmp, "...");
|
||||
}
|
||||
@@ -314,71 +265,58 @@ static void ui_712_format_bytes(const uint8_t *const data, uint8_t length)
|
||||
*/
|
||||
static bool ui_712_format_int(const uint8_t *const data,
|
||||
uint8_t length,
|
||||
const void *const field_ptr)
|
||||
{
|
||||
const void *const field_ptr) {
|
||||
uint256_t value256;
|
||||
uint128_t value128;
|
||||
int32_t value32;
|
||||
int16_t value16;
|
||||
|
||||
switch (get_struct_field_typesize(field_ptr) * 8)
|
||||
{
|
||||
switch (get_struct_field_typesize(field_ptr) * 8) {
|
||||
case 256:
|
||||
convertUint256BE(data, length, &value256);
|
||||
if (ui_712_field_shown())
|
||||
{
|
||||
if (ui_712_field_shown()) {
|
||||
tostring256_signed(&value256, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp));
|
||||
}
|
||||
break;
|
||||
case 128:
|
||||
convertUint128BE(data, length, &value128);
|
||||
if (ui_712_field_shown())
|
||||
{
|
||||
if (ui_712_field_shown()) {
|
||||
tostring128_signed(&value128, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp));
|
||||
}
|
||||
break;
|
||||
case 64:
|
||||
convertUint64BEto128(data, length, &value128);
|
||||
if (ui_712_field_shown())
|
||||
{
|
||||
if (ui_712_field_shown()) {
|
||||
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];
|
||||
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);
|
||||
if (ui_712_field_shown()) {
|
||||
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];
|
||||
for (int i = 0; i < length; ++i) {
|
||||
((uint8_t *) &value16)[length - 1 - i] = data[i];
|
||||
}
|
||||
if (ui_712_field_shown())
|
||||
{
|
||||
if (ui_712_field_shown()) {
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"%d",
|
||||
value16); // expanded to 32 bits
|
||||
value16); // expanded to 32 bits
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (ui_712_field_shown())
|
||||
{
|
||||
if (ui_712_field_shown()) {
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"%d",
|
||||
((int8_t*)data)[0]); // expanded to 32 bits
|
||||
((int8_t *) data)[0]); // expanded to 32 bits
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -395,13 +333,11 @@ static bool ui_712_format_int(const uint8_t *const data,
|
||||
* @param[in] data the data that needs formatting
|
||||
* @param[in] length its length
|
||||
*/
|
||||
static void ui_712_format_uint(const uint8_t *const data, uint8_t length)
|
||||
{
|
||||
static void ui_712_format_uint(const uint8_t *const data, uint8_t length) {
|
||||
uint256_t value256;
|
||||
|
||||
convertUint256BE(data, length, &value256);
|
||||
if (ui_712_field_shown())
|
||||
{
|
||||
if (ui_712_field_shown()) {
|
||||
tostring256(&value256, 10, strings.tmp.tmp, sizeof(strings.tmp.tmp));
|
||||
}
|
||||
}
|
||||
@@ -413,44 +349,37 @@ static void ui_712_format_uint(const uint8_t *const data, uint8_t length)
|
||||
* @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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (ui_ctx == NULL)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if ((key = get_struct_field_keyname(field_ptr, &key_len)) == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ui_712_field_shown() && !(ui_ctx->field_flags & UI_712_FIELD_NAME_PROVIDED))
|
||||
{
|
||||
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))
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (ui_712_format_addr(data, length) == false) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TYPE_SOL_BOOL:
|
||||
if (ui_712_format_bool(data, length) == false)
|
||||
{
|
||||
if (ui_712_format_bool(data, length) == false) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -459,8 +388,7 @@ bool ui_712_new_field(const void *const field_ptr, const uint8_t *const data,
|
||||
ui_712_format_bytes(data, length);
|
||||
break;
|
||||
case TYPE_SOL_INT:
|
||||
if (ui_712_format_int(data, length, field_ptr) == false)
|
||||
{
|
||||
if (ui_712_format_int(data, length, field_ptr) == false) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -473,8 +401,7 @@ bool ui_712_new_field(const void *const field_ptr, const uint8_t *const data,
|
||||
}
|
||||
|
||||
// Check if this field is supposed to be displayed
|
||||
if (ui_712_field_shown())
|
||||
{
|
||||
if (ui_712_field_shown()) {
|
||||
ui_712_redraw_generic_step();
|
||||
}
|
||||
return true;
|
||||
@@ -484,17 +411,14 @@ bool ui_712_new_field(const void *const field_ptr, const uint8_t *const data,
|
||||
* Used to signal that we are done with reviewing the structs and we can now have
|
||||
* the option to approve or reject the signature
|
||||
*/
|
||||
void ui_712_end_sign(void)
|
||||
{
|
||||
if (ui_ctx == NULL)
|
||||
{
|
||||
void ui_712_end_sign(void) {
|
||||
if (ui_ctx == NULL) {
|
||||
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))
|
||||
{
|
||||
if (N_storage.verbose_eip712 || (ui_ctx->filtering_mode == EIP712_FILTERING_FULL)) {
|
||||
ui_712_next_field();
|
||||
}
|
||||
}
|
||||
@@ -502,17 +426,13 @@ void ui_712_end_sign(void)
|
||||
/**
|
||||
* Initializes the UI context structure in memory
|
||||
*/
|
||||
bool ui_712_init(void)
|
||||
{
|
||||
if ((ui_ctx = MEM_ALLOC_AND_ALIGN_TYPE(*ui_ctx)))
|
||||
{
|
||||
bool ui_712_init(void) {
|
||||
if ((ui_ctx = MEM_ALLOC_AND_ALIGN_TYPE(*ui_ctx))) {
|
||||
ui_ctx->shown = false;
|
||||
ui_ctx->end_reached = false;
|
||||
ui_ctx->pos = UI_712_POS_REVIEW;
|
||||
ui_ctx->filtering_mode = EIP712_FILTERING_BASIC;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
return ui_ctx != NULL;
|
||||
@@ -521,8 +441,7 @@ bool ui_712_init(void)
|
||||
/**
|
||||
* Deinit function that simply unsets the struct pointer to NULL
|
||||
*/
|
||||
void ui_712_deinit(void)
|
||||
{
|
||||
void ui_712_deinit(void) {
|
||||
ui_ctx = NULL;
|
||||
}
|
||||
|
||||
@@ -532,8 +451,7 @@ void ui_712_deinit(void)
|
||||
* @param[in] e unused here, just needed to match the UI function signature
|
||||
* @return unused here, just needed to match the UI function signature
|
||||
*/
|
||||
unsigned int ui_712_approve(const bagl_element_t *e)
|
||||
{
|
||||
unsigned int ui_712_approve(const bagl_element_t *e) {
|
||||
ui_712_approve_cb(e);
|
||||
eip712_context_deinit();
|
||||
return 0;
|
||||
@@ -546,8 +464,7 @@ unsigned int ui_712_approve(const bagl_element_t *e)
|
||||
* @param[in] e unused here, just needed to match the UI function signature
|
||||
* @return unused here, just needed to match the UI function signature
|
||||
*/
|
||||
unsigned int ui_712_reject(const bagl_element_t *e)
|
||||
{
|
||||
unsigned int ui_712_reject(const bagl_element_t *e) {
|
||||
ui_712_reject_cb(e);
|
||||
eip712_context_deinit();
|
||||
return 0;
|
||||
@@ -559,14 +476,11 @@ unsigned int ui_712_reject(const bagl_element_t *e)
|
||||
* @param[in] show if this field should be shown on the device
|
||||
* @param[in] name_provided if a substitution name has been provided
|
||||
*/
|
||||
void ui_712_flag_field(bool show, bool name_provided)
|
||||
{
|
||||
if (show)
|
||||
{
|
||||
void ui_712_flag_field(bool show, bool name_provided) {
|
||||
if (show) {
|
||||
ui_ctx->field_flags |= UI_712_FIELD_SHOWN;
|
||||
}
|
||||
if (name_provided)
|
||||
{
|
||||
if (name_provided) {
|
||||
ui_ctx->field_flags |= UI_712_FIELD_NAME_PROVIDED;
|
||||
}
|
||||
}
|
||||
@@ -576,8 +490,7 @@ void ui_712_flag_field(bool show, bool name_provided)
|
||||
*
|
||||
* @param[in] the new filtering mode
|
||||
*/
|
||||
void ui_712_set_filtering_mode(e_eip712_filtering_mode mode)
|
||||
{
|
||||
void ui_712_set_filtering_mode(e_eip712_filtering_mode mode) {
|
||||
ui_ctx->filtering_mode = mode;
|
||||
}
|
||||
|
||||
@@ -586,16 +499,14 @@ void ui_712_set_filtering_mode(e_eip712_filtering_mode mode)
|
||||
*
|
||||
* @return current filtering mode
|
||||
*/
|
||||
e_eip712_filtering_mode ui_712_get_filtering_mode(void)
|
||||
{
|
||||
e_eip712_filtering_mode ui_712_get_filtering_mode(void) {
|
||||
return ui_ctx->filtering_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all the UI struct field flags
|
||||
*/
|
||||
void ui_712_field_flags_reset(void)
|
||||
{
|
||||
void ui_712_field_flags_reset(void) {
|
||||
ui_ctx->field_flags = 0;
|
||||
}
|
||||
|
||||
@@ -604,12 +515,10 @@ void ui_712_field_flags_reset(void)
|
||||
*
|
||||
* Makes it so the user will have to go through a "Review struct" screen
|
||||
*/
|
||||
void ui_712_queue_struct_to_review(void)
|
||||
{
|
||||
if (N_storage.verbose_eip712)
|
||||
{
|
||||
void ui_712_queue_struct_to_review(void) {
|
||||
if (N_storage.verbose_eip712) {
|
||||
ui_ctx->structs_to_review += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
@@ -6,30 +6,21 @@
|
||||
#include <stdint.h>
|
||||
#include "ux.h"
|
||||
|
||||
#define UI_712_FIELD_SHOWN (1 << 0)
|
||||
#define UI_712_FIELD_NAME_PROVIDED (1 << 1)
|
||||
#define UI_712_FIELD_SHOWN (1 << 0)
|
||||
#define UI_712_FIELD_NAME_PROVIDED (1 << 1)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EIP712_FILTERING_BASIC,
|
||||
EIP712_FILTERING_FULL
|
||||
} e_eip712_filtering_mode;
|
||||
typedef enum { EIP712_FILTERING_BASIC, EIP712_FILTERING_FULL } e_eip712_filtering_mode;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UI_712_POS_REVIEW,
|
||||
UI_712_POS_END
|
||||
} e_ui_position;
|
||||
typedef enum { UI_712_POS_REVIEW, UI_712_POS_END } e_ui_position;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
bool shown;
|
||||
bool end_reached;
|
||||
e_ui_position pos;
|
||||
uint8_t filtering_mode;
|
||||
uint8_t field_flags;
|
||||
uint8_t structs_to_review;
|
||||
} t_ui_context;
|
||||
} t_ui_context;
|
||||
|
||||
bool ui_712_init(void);
|
||||
void ui_712_deinit(void);
|
||||
@@ -41,15 +32,15 @@ unsigned int ui_712_approve(const bagl_element_t *e);
|
||||
unsigned int ui_712_reject(const bagl_element_t *e);
|
||||
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_message_hash(void);
|
||||
void ui_712_redraw_generic_step(void);
|
||||
void ui_712_flag_field(bool show, bool name_provided);
|
||||
void ui_712_field_flags_reset(void);
|
||||
void ui_712_finalize_field(void);
|
||||
void ui_712_set_filtering_mode(e_eip712_filtering_mode mode);
|
||||
void ui_712_message_hash(void);
|
||||
void ui_712_redraw_generic_step(void);
|
||||
void ui_712_flag_field(bool show, bool name_provided);
|
||||
void ui_712_field_flags_reset(void);
|
||||
void ui_712_finalize_field(void);
|
||||
void ui_712_set_filtering_mode(e_eip712_filtering_mode mode);
|
||||
e_eip712_filtering_mode ui_712_get_filtering_mode(void);
|
||||
void ui_712_queue_struct_to_review(void);
|
||||
void ui_712_queue_struct_to_review(void);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // UI_LOGIC_712_H_
|
||||
#endif // UI_LOGIC_712_H_
|
||||
|
||||
@@ -5,15 +5,14 @@
|
||||
|
||||
static const uint8_t EIP_712_MAGIC[] = {0x19, 0x01};
|
||||
|
||||
unsigned int ui_712_approve_cb(const bagl_element_t *e)
|
||||
{
|
||||
unsigned int ui_712_approve_cb(const bagl_element_t *e) {
|
||||
uint8_t privateKeyData[INT256_LENGTH];
|
||||
uint8_t hash[INT256_LENGTH];
|
||||
uint8_t signature[100];
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint32_t tx = 0;
|
||||
|
||||
(void)e;
|
||||
(void) e;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_keccak_init(&global_sha3, 256);
|
||||
cx_hash((cx_hash_t *) &global_sha3,
|
||||
@@ -57,12 +56,10 @@ unsigned int ui_712_approve_cb(const bagl_element_t *e)
|
||||
&info);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
G_io_apdu_buffer[0] = 27;
|
||||
if (info & CX_ECCINFO_PARITY_ODD)
|
||||
{
|
||||
if (info & CX_ECCINFO_PARITY_ODD) {
|
||||
G_io_apdu_buffer[0]++;
|
||||
}
|
||||
if (info & CX_ECCINFO_xGTn)
|
||||
{
|
||||
if (info & CX_ECCINFO_xGTn) {
|
||||
G_io_apdu_buffer[0] += 2;
|
||||
}
|
||||
format_signature_out(signature);
|
||||
@@ -77,9 +74,8 @@ unsigned int ui_712_approve_cb(const bagl_element_t *e)
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int ui_712_reject_cb(const bagl_element_t *e)
|
||||
{
|
||||
(void)e;
|
||||
unsigned int ui_712_reject_cb(const bagl_element_t *e) {
|
||||
(void) e;
|
||||
reset_app_context();
|
||||
G_io_apdu_buffer[0] = 0x69;
|
||||
G_io_apdu_buffer[1] = 0x85;
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
unsigned int ui_712_approve_cb(const bagl_element_t *e);
|
||||
unsigned int ui_712_reject_cb(const bagl_element_t *e);
|
||||
|
||||
#endif // COMMON_EIP712_H_
|
||||
#endif // COMMON_EIP712_H_
|
||||
|
||||
@@ -11,8 +11,8 @@ void handleSignEIP712Message_v0(uint8_t p1,
|
||||
uint8_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
(void)tx;
|
||||
(void)p2;
|
||||
(void) tx;
|
||||
(void) p2;
|
||||
if (p1 != 00) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
@@ -25,9 +25,7 @@ void handleSignEIP712Message_v0(uint8_t p1,
|
||||
if ((workBuffer == NULL) || (dataLength < (KECCAK256_HASH_BYTESIZE * 2))) {
|
||||
THROW(0x6a80);
|
||||
}
|
||||
memmove(tmpCtx.messageSigningContext712.domainHash,
|
||||
workBuffer,
|
||||
KECCAK256_HASH_BYTESIZE);
|
||||
memmove(tmpCtx.messageSigningContext712.domainHash, workBuffer, KECCAK256_HASH_BYTESIZE);
|
||||
memmove(tmpCtx.messageSigningContext712.messageHash,
|
||||
workBuffer + KECCAK256_HASH_BYTESIZE,
|
||||
KECCAK256_HASH_BYTESIZE);
|
||||
|
||||
Reference in New Issue
Block a user