UI handling WIP
This commit is contained in:
@@ -172,5 +172,6 @@ void handleStarkwareUnsafeSign(uint8_t p1,
|
|||||||
|
|
||||||
bool handle_eip712_struct_def(const uint8_t *const apdu_buf);
|
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_struct_impl(const uint8_t *const apdu_buf);
|
||||||
|
bool handle_eip712_sign(const uint8_t *const apdu_buf);
|
||||||
|
|
||||||
#endif // _APDU_CONSTANTS_H_
|
#endif // _APDU_CONSTANTS_H_
|
||||||
|
|||||||
23
src/main.c
23
src/main.c
@@ -663,13 +663,20 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case INS_SIGN_EIP_712_MESSAGE:
|
case INS_SIGN_EIP_712_MESSAGE:
|
||||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_ITEMS);
|
if (G_io_apdu_buffer[OFFSET_P2] == 0)
|
||||||
handleSignEIP712Message_v0(G_io_apdu_buffer[OFFSET_P1],
|
{
|
||||||
G_io_apdu_buffer[OFFSET_P2],
|
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_ITEMS);
|
||||||
G_io_apdu_buffer + OFFSET_CDATA,
|
handleSignEIP712Message_v0(G_io_apdu_buffer[OFFSET_P1],
|
||||||
G_io_apdu_buffer[OFFSET_LC],
|
G_io_apdu_buffer[OFFSET_P2],
|
||||||
flags,
|
G_io_apdu_buffer + OFFSET_CDATA,
|
||||||
tx);
|
G_io_apdu_buffer[OFFSET_LC],
|
||||||
|
flags,
|
||||||
|
tx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handle_eip712_sign(G_io_apdu_buffer);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef HAVE_ETH2
|
#ifdef HAVE_ETH2
|
||||||
@@ -696,10 +703,12 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
case INS_EIP712_STRUCT_DEF:
|
case INS_EIP712_STRUCT_DEF:
|
||||||
|
*flags |= IO_ASYNCH_REPLY;
|
||||||
handle_eip712_struct_def(G_io_apdu_buffer);
|
handle_eip712_struct_def(G_io_apdu_buffer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INS_EIP712_STRUCT_IMPL:
|
case INS_EIP712_STRUCT_IMPL:
|
||||||
|
*flags |= IO_ASYNCH_REPLY;
|
||||||
handle_eip712_struct_impl(G_io_apdu_buffer);
|
handle_eip712_struct_impl(G_io_apdu_buffer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "sol_typenames.h"
|
#include "sol_typenames.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "field_hash.h"
|
#include "field_hash.h"
|
||||||
|
#include "ui_logic.h"
|
||||||
|
|
||||||
uint8_t *typenames_array;
|
uint8_t *typenames_array;
|
||||||
uint8_t *structs_array;
|
uint8_t *structs_array;
|
||||||
@@ -35,6 +36,11 @@ bool init_eip712_context(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ui_712_init() == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// set types pointer
|
// set types pointer
|
||||||
if ((structs_array = mem_alloc(sizeof(uint8_t))) == NULL)
|
if ((structs_array = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||||
{
|
{
|
||||||
@@ -45,3 +51,5 @@ bool init_eip712_context(void)
|
|||||||
*structs_array = 0;
|
*structs_array = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Make a deinit function
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "field_hash.h"
|
#include "field_hash.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "shared_context.h"
|
#include "shared_context.h"
|
||||||
|
#include "ui_logic.h"
|
||||||
|
|
||||||
|
|
||||||
// lib functions
|
// lib functions
|
||||||
@@ -419,18 +420,34 @@ bool handle_eip712_struct_impl(const uint8_t *const apdu_buf)
|
|||||||
apdu_buf[OFFSET_INS]);
|
apdu_buf[OFFSET_INS]);
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
if (ret)
|
if (!ret)
|
||||||
{
|
|
||||||
G_io_apdu_buffer[0] = 0x90;
|
|
||||||
G_io_apdu_buffer[1] = 0x00;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
// Send back the response, do not restart the event loop
|
||||||
G_io_apdu_buffer[0] = 0x6A;
|
G_io_apdu_buffer[0] = 0x6A;
|
||||||
G_io_apdu_buffer[1] = 0x80;
|
G_io_apdu_buffer[1] = 0x80;
|
||||||
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||||
}
|
}
|
||||||
//*flags |= IO_ASYNCH_REPLY;
|
|
||||||
// Send back the response, do not restart the event loop
|
|
||||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool handle_eip712_sign(const uint8_t *const apdu_buf)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
if (apdu_buf[OFFSET_LC] < 1) {
|
||||||
|
PRINTF("Invalid data\n");
|
||||||
|
THROW(0x6a80);
|
||||||
|
}
|
||||||
|
tmpCtx.messageSigningContext712.pathLength = apdu_buf[OFFSET_DATA];
|
||||||
|
if ((tmpCtx.messageSigningContext712.pathLength < 0x01) ||
|
||||||
|
(tmpCtx.messageSigningContext712.pathLength > MAX_BIP32_PATH)) {
|
||||||
|
PRINTF("Invalid path\n");
|
||||||
|
THROW(0x6a80);
|
||||||
|
}
|
||||||
|
for (i = 0; i < tmpCtx.messageSigningContext712.pathLength; i++) {
|
||||||
|
tmpCtx.messageSigningContext712.bip32Path[i] = U4BE(apdu_buf + OFFSET_LC + 1 + (i * 4), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_712_end_sign();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "mem_utils.h"
|
#include "mem_utils.h"
|
||||||
#include "eip712.h"
|
#include "eip712.h"
|
||||||
#include "shared_context.h"
|
#include "shared_context.h"
|
||||||
|
#include "ui_logic.h"
|
||||||
|
|
||||||
static s_field_hashing *fh = NULL;
|
static s_field_hashing *fh = NULL;
|
||||||
|
|
||||||
@@ -145,6 +146,7 @@ bool field_hash(const uint8_t *data,
|
|||||||
// deallocate it
|
// deallocate it
|
||||||
mem_dealloc(len);
|
mem_dealloc(len);
|
||||||
|
|
||||||
|
ui_712_new_field(field_ptr, data, data_length);
|
||||||
path_advance();
|
path_advance();
|
||||||
fh->state = FHS_IDLE;
|
fh->state = FHS_IDLE;
|
||||||
}
|
}
|
||||||
@@ -154,6 +156,9 @@ bool field_hash(const uint8_t *data,
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
G_io_apdu_buffer[0] = 0x90;
|
||||||
|
G_io_apdu_buffer[1] = 0x00;
|
||||||
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "shared_context.h"
|
#include "shared_context.h"
|
||||||
#include "ethUtils.h"
|
#include "ethUtils.h"
|
||||||
#include "mem_utils.h"
|
#include "mem_utils.h"
|
||||||
|
#include "ui_logic.h"
|
||||||
|
|
||||||
static s_path *path_struct = NULL;
|
static s_path *path_struct = NULL;
|
||||||
|
|
||||||
@@ -295,6 +296,7 @@ bool path_set_root(const char *const struct_name, uint8_t name_length)
|
|||||||
{
|
{
|
||||||
if (path_struct == NULL)
|
if (path_struct == NULL)
|
||||||
{
|
{
|
||||||
|
PRINTF("NULL check failed!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,6 +304,12 @@ bool path_set_root(const char *const struct_name, uint8_t 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)
|
||||||
|
{
|
||||||
|
PRINTF("%c", struct_name[i]);
|
||||||
|
}
|
||||||
|
PRINTF(")!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,6 +323,7 @@ bool path_set_root(const char *const struct_name, uint8_t name_length)
|
|||||||
cx_keccak_init(hash_ctx, 256); // init hash
|
cx_keccak_init(hash_ctx, 256); // init hash
|
||||||
if ((thash_ptr = type_hash(structs_array, struct_name, name_length)) == NULL)
|
if ((thash_ptr = type_hash(structs_array, struct_name, name_length)) == NULL)
|
||||||
{
|
{
|
||||||
|
PRINTF("Memory allocation failed!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// start the progressive hash on it
|
// start the progressive hash on it
|
||||||
@@ -347,6 +356,7 @@ bool path_set_root(const char *const struct_name, uint8_t name_length)
|
|||||||
|
|
||||||
// because the first field could be a struct type
|
// because the first field could be a struct type
|
||||||
path_update();
|
path_update();
|
||||||
|
ui_712_new_root_struct(path_struct->root_struct);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,6 +468,9 @@ bool path_new_array_depth(uint8_t size)
|
|||||||
cx_keccak_init(hash_ctx, 256); // init hash
|
cx_keccak_init(hash_ctx, 256); // init hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G_io_apdu_buffer[0] = 0x90;
|
||||||
|
G_io_apdu_buffer[1] = 0x00;
|
||||||
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
53
src_features/signMessageEIP712/ui_flow_712.c
Normal file
53
src_features/signMessageEIP712/ui_flow_712.c
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include "ui_flow_712.h"
|
||||||
|
#include "ui_logic.h"
|
||||||
|
#include "shared_context.h" // strings
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
UX_STEP_NOCB(
|
||||||
|
ux_712_step_review,
|
||||||
|
pnn,
|
||||||
|
{
|
||||||
|
&C_icon_eye,
|
||||||
|
"Review",
|
||||||
|
"typed message",
|
||||||
|
});
|
||||||
|
UX_STEP_NOCB(
|
||||||
|
ux_712_step_dynamic,
|
||||||
|
bnnn_paging,
|
||||||
|
{
|
||||||
|
.title = strings.tmp.tmp2,
|
||||||
|
.text = strings.tmp.tmp,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
UX_STEP_INIT(
|
||||||
|
ux_712_step_dummy,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
{
|
||||||
|
ui_712_next_field();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
UX_STEP_CB(
|
||||||
|
ux_712_step_approve,
|
||||||
|
pb,
|
||||||
|
NULL,//io_seproxyhal_touch_signMessage712_ok(NULL),
|
||||||
|
{
|
||||||
|
&C_icon_validate_14,
|
||||||
|
"Approve",
|
||||||
|
});
|
||||||
|
UX_STEP_CB(
|
||||||
|
ux_712_step_reject,
|
||||||
|
pb,
|
||||||
|
NULL,//io_seproxyhal_touch_signMessage712_cancel(NULL),
|
||||||
|
{
|
||||||
|
&C_icon_crossmark,
|
||||||
|
"Reject",
|
||||||
|
});
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
UX_FLOW(ux_712_flow,
|
||||||
|
&ux_712_step_review,
|
||||||
|
&ux_712_step_dynamic,
|
||||||
|
&ux_712_step_dummy,
|
||||||
|
&ux_712_step_approve,
|
||||||
|
&ux_712_step_reject);
|
||||||
8
src_features/signMessageEIP712/ui_flow_712.h
Normal file
8
src_features/signMessageEIP712/ui_flow_712.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef UI_FLOW_712_H_
|
||||||
|
#define UI_FLOW_712_H_
|
||||||
|
|
||||||
|
#include "ux_flow_engine.h"
|
||||||
|
|
||||||
|
extern const ux_flow_step_t* const ux_712_flow[];
|
||||||
|
|
||||||
|
#endif // UI_FLOW_712_H_
|
||||||
112
src_features/signMessageEIP712/ui_logic.c
Normal file
112
src_features/signMessageEIP712/ui_logic.c
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "ui_logic.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "mem_utils.h"
|
||||||
|
#include "os_io.h"
|
||||||
|
#include "ux_flow_engine.h"
|
||||||
|
#include "ui_flow_712.h"
|
||||||
|
#include "shared_context.h"
|
||||||
|
#include "eip712.h" // get_struct_name
|
||||||
|
|
||||||
|
static t_ui_context *ui_ctx = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on the intermediate dummy screen between the dynamic step
|
||||||
|
* && the approve/reject screen
|
||||||
|
*/
|
||||||
|
void ui_712_next_field(void)
|
||||||
|
{
|
||||||
|
if (!ui_ctx->end_reached)
|
||||||
|
{
|
||||||
|
// reply to previous APDU
|
||||||
|
G_io_apdu_buffer[0] = 0x90;
|
||||||
|
G_io_apdu_buffer[1] = 0x00;
|
||||||
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ui_ctx->pos == UI_712_POS_REVIEW)
|
||||||
|
{
|
||||||
|
ux_flow_next();
|
||||||
|
ui_ctx->pos = UI_712_POS_END;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ux_flow_prev();
|
||||||
|
ui_ctx->pos = UI_712_POS_REVIEW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to notify of a new struct to review (domain or message)
|
||||||
|
*/
|
||||||
|
void ui_712_new_root_struct(const void *const struct_ptr)
|
||||||
|
{
|
||||||
|
strcpy(strings.tmp.tmp2, "Review struct");
|
||||||
|
const char *struct_name;
|
||||||
|
uint8_t struct_name_length;
|
||||||
|
if ((struct_name = get_struct_name(struct_ptr, &struct_name_length)) != NULL)
|
||||||
|
{
|
||||||
|
strncpy(strings.tmp.tmp, struct_name, struct_name_length);
|
||||||
|
strings.tmp.tmp[struct_name_length] = '\0';
|
||||||
|
}
|
||||||
|
if (!ui_ctx->shown)
|
||||||
|
{
|
||||||
|
ux_flow_init(0, ux_712_flow, NULL);
|
||||||
|
ui_ctx->shown = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ux_flow_prev();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to notify of a new field to review in the current struct (key + value)
|
||||||
|
*
|
||||||
|
* @param[in] field_ptr pointer to the new struct field
|
||||||
|
* @param[in] data pointer to the field's raw value
|
||||||
|
* @param[in] length field's raw value byte-length
|
||||||
|
*/
|
||||||
|
void 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 ((key = get_struct_field_keyname(field_ptr, &key_len)) != NULL)
|
||||||
|
{
|
||||||
|
strncpy(strings.tmp.tmp2, key, MIN(key_len, sizeof(strings.tmp.tmp2) - 1));
|
||||||
|
strings.tmp.tmp2[key_len] = '\0';
|
||||||
|
}
|
||||||
|
// TODO: Encode data as string based on data type
|
||||||
|
(void)data;
|
||||||
|
(void)length;
|
||||||
|
strcpy(strings.tmp.tmp, "Field value");
|
||||||
|
ux_flow_prev();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
ui_ctx->end_reached = true;
|
||||||
|
ui_712_next_field();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the UI context structure in memory
|
||||||
|
*/
|
||||||
|
bool ui_712_init(void)
|
||||||
|
{
|
||||||
|
if ((ui_ctx = MEM_ALLOC_AND_ALIGN_TO_TYPE(sizeof(*ui_ctx), *ui_ctx)))
|
||||||
|
{
|
||||||
|
ui_ctx->shown = false;
|
||||||
|
ui_ctx->end_reached = false;
|
||||||
|
ui_ctx->pos = UI_712_POS_REVIEW;
|
||||||
|
}
|
||||||
|
return ui_ctx != NULL;
|
||||||
|
}
|
||||||
25
src_features/signMessageEIP712/ui_logic.h
Normal file
25
src_features/signMessageEIP712/ui_logic.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef UI_LOGIC_712_H_
|
||||||
|
#define UI_LOGIC_712_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
UI_712_POS_REVIEW,
|
||||||
|
UI_712_POS_END
|
||||||
|
} e_ui_position;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
bool shown;
|
||||||
|
bool end_reached;
|
||||||
|
e_ui_position pos;
|
||||||
|
} t_ui_context;
|
||||||
|
|
||||||
|
bool ui_712_init(void);
|
||||||
|
void ui_712_next_field(void);
|
||||||
|
void ui_712_new_root_struct(const void *const struct_ptr);
|
||||||
|
void ui_712_new_field(const void *const field_ptr, const uint8_t *const data, uint8_t length);
|
||||||
|
void ui_712_end_sign(void);
|
||||||
|
|
||||||
|
#endif // UI_LOGIC_712_H_
|
||||||
@@ -13,7 +13,7 @@ void handleSignEIP712Message_v0(uint8_t p1,
|
|||||||
|
|
||||||
UNUSED(tx);
|
UNUSED(tx);
|
||||||
if ((p1 != 00) || (p2 != 00)) {
|
if ((p1 != 00) || (p2 != 00)) {
|
||||||
//THROW(0x6B00); // TODO: TMP
|
THROW(0x6B00);
|
||||||
}
|
}
|
||||||
if (appState != APP_STATE_IDLE) {
|
if (appState != APP_STATE_IDLE) {
|
||||||
reset_app_context();
|
reset_app_context();
|
||||||
@@ -21,17 +21,11 @@ void handleSignEIP712Message_v0(uint8_t p1,
|
|||||||
|
|
||||||
workBuffer = parseBip32(workBuffer, &dataLength, &tmpCtx.messageSigningContext.bip32);
|
workBuffer = parseBip32(workBuffer, &dataLength, &tmpCtx.messageSigningContext.bip32);
|
||||||
|
|
||||||
if (workBuffer == NULL) {
|
if ((workBuffer == NULL) || (dataLength < (32 + 32))) {
|
||||||
THROW(0x6a80);
|
THROW(0x6a80);
|
||||||
}
|
}
|
||||||
if (p2 == 0) // TODO: TMP
|
memmove(tmpCtx.messageSigningContext712.domainHash, workBuffer, 32);
|
||||||
{
|
memmove(tmpCtx.messageSigningContext712.messageHash, workBuffer + 32, 32);
|
||||||
if (dataLength < (32 + 32)) {
|
|
||||||
THROW(0x6a80);
|
|
||||||
}
|
|
||||||
memmove(tmpCtx.messageSigningContext712.domainHash, workBuffer, 32);
|
|
||||||
memmove(tmpCtx.messageSigningContext712.messageHash, workBuffer + 32, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NO_CONSENT
|
#ifdef NO_CONSENT
|
||||||
io_seproxyhal_touch_signMessage_ok(NULL);
|
io_seproxyhal_touch_signMessage_ok(NULL);
|
||||||
|
|||||||
Reference in New Issue
Block a user