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_impl(const uint8_t *const apdu_buf);
|
||||
bool handle_eip712_sign(const uint8_t *const apdu_buf);
|
||||
|
||||
#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;
|
||||
|
||||
case INS_SIGN_EIP_712_MESSAGE:
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_ITEMS);
|
||||
handleSignEIP712Message_v0(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
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],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle_eip712_sign(G_io_apdu_buffer);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef HAVE_ETH2
|
||||
@@ -696,10 +703,12 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
|
||||
#endif
|
||||
|
||||
case INS_EIP712_STRUCT_DEF:
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
handle_eip712_struct_def(G_io_apdu_buffer);
|
||||
break;
|
||||
|
||||
case INS_EIP712_STRUCT_IMPL:
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
handle_eip712_struct_impl(G_io_apdu_buffer);
|
||||
break;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "sol_typenames.h"
|
||||
#include "path.h"
|
||||
#include "field_hash.h"
|
||||
#include "ui_logic.h"
|
||||
|
||||
uint8_t *typenames_array;
|
||||
uint8_t *structs_array;
|
||||
@@ -35,6 +36,11 @@ bool init_eip712_context(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ui_712_init() == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// set types pointer
|
||||
if ((structs_array = mem_alloc(sizeof(uint8_t))) == NULL)
|
||||
{
|
||||
@@ -45,3 +51,5 @@ bool init_eip712_context(void)
|
||||
*structs_array = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Make a deinit function
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "field_hash.h"
|
||||
#include "path.h"
|
||||
#include "shared_context.h"
|
||||
#include "ui_logic.h"
|
||||
|
||||
|
||||
// lib functions
|
||||
@@ -419,18 +420,34 @@ bool handle_eip712_struct_impl(const uint8_t *const apdu_buf)
|
||||
apdu_buf[OFFSET_INS]);
|
||||
ret = false;
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
G_io_apdu_buffer[0] = 0x90;
|
||||
G_io_apdu_buffer[1] = 0x00;
|
||||
}
|
||||
else
|
||||
if (!ret)
|
||||
{
|
||||
// Send back the response, do not restart the event loop
|
||||
G_io_apdu_buffer[0] = 0x6A;
|
||||
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;
|
||||
}
|
||||
|
||||
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 "eip712.h"
|
||||
#include "shared_context.h"
|
||||
#include "ui_logic.h"
|
||||
|
||||
static s_field_hashing *fh = NULL;
|
||||
|
||||
@@ -145,6 +146,7 @@ bool field_hash(const uint8_t *data,
|
||||
// deallocate it
|
||||
mem_dealloc(len);
|
||||
|
||||
ui_712_new_field(field_ptr, data, data_length);
|
||||
path_advance();
|
||||
fh->state = FHS_IDLE;
|
||||
}
|
||||
@@ -154,6 +156,9 @@ bool field_hash(const uint8_t *data,
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "shared_context.h"
|
||||
#include "ethUtils.h"
|
||||
#include "mem_utils.h"
|
||||
#include "ui_logic.h"
|
||||
|
||||
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)
|
||||
{
|
||||
PRINTF("NULL check failed!\n");
|
||||
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)
|
||||
{
|
||||
PRINTF("Struct name not found (");
|
||||
for (int i = 0; i < name_length; ++i)
|
||||
{
|
||||
PRINTF("%c", struct_name[i]);
|
||||
}
|
||||
PRINTF(")!\n");
|
||||
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
|
||||
if ((thash_ptr = type_hash(structs_array, struct_name, name_length)) == NULL)
|
||||
{
|
||||
PRINTF("Memory allocation failed!\n");
|
||||
return false;
|
||||
}
|
||||
// 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
|
||||
path_update();
|
||||
ui_712_new_root_struct(path_struct->root_struct);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -458,6 +468,9 @@ bool path_new_array_depth(uint8_t size)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
if ((p1 != 00) || (p2 != 00)) {
|
||||
//THROW(0x6B00); // TODO: TMP
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
@@ -21,17 +21,11 @@ void handleSignEIP712Message_v0(uint8_t p1,
|
||||
|
||||
workBuffer = parseBip32(workBuffer, &dataLength, &tmpCtx.messageSigningContext.bip32);
|
||||
|
||||
if (workBuffer == NULL) {
|
||||
if ((workBuffer == NULL) || (dataLength < (32 + 32))) {
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if (p2 == 0) // TODO: TMP
|
||||
{
|
||||
if (dataLength < (32 + 32)) {
|
||||
THROW(0x6a80);
|
||||
}
|
||||
memmove(tmpCtx.messageSigningContext712.domainHash, workBuffer, 32);
|
||||
memmove(tmpCtx.messageSigningContext712.messageHash, workBuffer + 32, 32);
|
||||
}
|
||||
memmove(tmpCtx.messageSigningContext712.domainHash, workBuffer, 32);
|
||||
memmove(tmpCtx.messageSigningContext712.messageHash, workBuffer + 32, 32);
|
||||
|
||||
#ifdef NO_CONSENT
|
||||
io_seproxyhal_touch_signMessage_ok(NULL);
|
||||
|
||||
Reference in New Issue
Block a user