UI handling WIP

This commit is contained in:
Alexandre Paillier
2022-05-12 17:29:35 +02:00
parent b8424d1a21
commit 9f29a7caa2
11 changed files with 271 additions and 26 deletions

View File

@@ -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_

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View 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);

View 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_

View 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;
}

View 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_

View File

@@ -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);