From d503f28d532015797806559c336ded45e15ec547 Mon Sep 17 00:00:00 2001 From: Jan Mazak Date: Wed, 14 Feb 2024 16:03:28 +0100 Subject: [PATCH] todo --- src/signMsg.c | 53 ++++++++++++++++++++++++------------------- src/signMsg.h | 7 ++++-- src/signMsg_ui.c | 58 +++++++++++++++++++++++++++++++++++++----------- src/signMsg_ui.h | 3 ++- 4 files changed, 82 insertions(+), 39 deletions(-) diff --git a/src/signMsg.c b/src/signMsg.c index e5d332b7..924de7bb 100644 --- a/src/signMsg.c +++ b/src/signMsg.c @@ -44,11 +44,21 @@ void signMsg_handleInitAPDU( TRACE_BUFFER(wireDataBuffer, wireDataSize); read_view_t view = make_read_view(wireDataBuffer, wireDataBuffer + wireDataSize); + ctx->msgLength = parse_u4be(&view); + TRACE("Msg length: %d", ctx->msgLength); + ctx->remainingBytes = ctx->msgLength; + view_skipBytes(&view, bip44_parseFromWire(&ctx->witnessPath, VIEW_REMAINING_TO_TUPLE_BUF_SIZE(&view))); - TRACE(); + TRACE("Witness path:"); BIP44_PRINTF(&ctx->witnessPath); PRINTF("\n"); + ctx->hashPayload = parseBool(&view); + TRACE("Hash payload: %d", ctx->hashPayload); + + ctx->isAscii = parseBool(&view); + TRACE("Is ascii: %d", ctx->isAscii); + ctx->addressFieldType = parse_u1be(&view); TRACE("Address field type: %d", ctx->addressFieldType); switch (ctx->addressFieldType) { @@ -62,19 +72,6 @@ void signMsg_handleInitAPDU( THROW(ERR_INVALID_DATA); } - ctx->isAscii = parseBool(&view); - TRACE("Is ascii: %d", ctx->isAscii); - - ctx->hashPayload = parseBool(&view); - TRACE("Hash payload: %d", ctx->hashPayload); - - ctx->msgLength = parse_u4be(&view); - TRACE("Remaining msg length: %d", ctx->msgLength); - if (!ctx->hashPayload) { - VALIDATE(ctx->msgLength <= MAX_CIP8_MSG_CHUNK_SIZE, ERR_INVALID_DATA); - } - ctx->remainingBytes = ctx->msgLength; - VALIDATE(view_remainingSize(&view) == 0, ERR_INVALID_DATA); } @@ -116,6 +113,8 @@ static void signMsg_handleMsgChunkAPDU(const uint8_t* wireDataBuffer, size_t wir } } { + ctx->receivedChunks += 1; + TRACE_BUFFER(wireDataBuffer, wireDataSize); read_view_t view = make_read_view(wireDataBuffer, wireDataBuffer + wireDataSize); @@ -123,11 +122,21 @@ static void signMsg_handleMsgChunkAPDU(const uint8_t* wireDataBuffer, size_t wir const size_t chunkSize = parse_u4be(&view); TRACE("chunkSize = %u", chunkSize); - VALIDATE(chunkSize <= MAX_CIP8_MSG_CHUNK_SIZE, ERR_INVALID_DATA); + // we allow empty message, displayed in the ui at this stage; it comes with empty chunk if (ctx->msgLength > 0) { VALIDATE(chunkSize > 0, ERR_INVALID_DATA); } + if (ctx->receivedChunks == 1) { + if (ctx->isAscii) { + VALIDATE(chunkSize <= MAX_CIP8_MSG_FIRST_CHUNK_ASCII_SIZE, ERR_INVALID_DATA); + } else { + VALIDATE(chunkSize <= MAX_CIP8_MSG_FIRST_CHUNK_HEX_SIZE, ERR_INVALID_DATA); + } + } else { + VALIDATE(chunkSize <= MAX_CIP8_MSG_HIDDEN_CHUNK_SIZE, ERR_INVALID_DATA); + } + VALIDATE(chunkSize <= ctx->remainingBytes, ERR_INVALID_DATA); ctx->remainingBytes -= chunkSize; ctx->chunkSize = chunkSize; @@ -139,8 +148,6 @@ static void signMsg_handleMsgChunkAPDU(const uint8_t* wireDataBuffer, size_t wir } VALIDATE(view_remainingSize(&view) == 0, ERR_INVALID_DATA); - - ctx->receivedChunks += 1; } { TRACE("Adding msg chunk to msg hash"); @@ -150,21 +157,21 @@ static void signMsg_handleMsgChunkAPDU(const uint8_t* wireDataBuffer, size_t wir if (ctx->receivedChunks == 1) { if (!ctx->hashPayload) { // for non-hashed payload, we expect only a single chunk - // TODO this does not work because only 200 B can be displayed at once - // so for hashed payload, chunks of size 250 can be processed and not shown - // but for non-hashed payload, all chunks will be shown? and they can be sized at most 90 - // for UI, there is a limit of 200 chars on the second line VALIDATE(ctx->remainingBytes == 0, ERR_INVALID_DATA); } - ctx->ui_step = HANDLE_CHUNK_STEP_DISPLAY; + ctx->ui_step = HANDLE_CHUNK_STEP_INTRO; signMsg_handleChunk_ui_runStep(); } else { // for non-hashed payload, we expect only a single chunk, // so the state should be SIGN_MSG_STAGE_CONFIRM already - ASSERT(!ctx->hashPayload); + ASSERT(ctx->hashPayload); // the chunk has been added to msg hash, nothing more to do, and no UI respondSuccessEmptyMsg(); + + if (ctx->remainingBytes == 0) { + ctx->stage = SIGN_MSG_STAGE_CONFIRM; + } } } diff --git a/src/signMsg.h b/src/signMsg.h index 94aa4d3e..f2dcb356 100644 --- a/src/signMsg.h +++ b/src/signMsg.h @@ -11,7 +11,10 @@ handler_fn_t signMsg_handleAPDU; -#define MAX_CIP8_MSG_CHUNK_SIZE 250 +// Note: this cannot be increased, there is a limit of 200 chars in the UI +#define MAX_CIP8_MSG_FIRST_CHUNK_ASCII_SIZE 198 +#define MAX_CIP8_MSG_FIRST_CHUNK_HEX_SIZE 99 +#define MAX_CIP8_MSG_HIDDEN_CHUNK_SIZE 250 typedef enum { SIGN_MSG_STAGE_NONE = 0, @@ -32,7 +35,7 @@ typedef struct { size_t remainingBytes; size_t receivedChunks; - uint8_t chunk[MAX_CIP8_MSG_CHUNK_SIZE]; + uint8_t chunk[MAX_CIP8_MSG_HIDDEN_CHUNK_SIZE]; size_t chunkSize; blake2b_224_context_t msgHashCtx; diff --git a/src/signMsg_ui.c b/src/signMsg_ui.c index 2ed25b05..28e31c2d 100644 --- a/src/signMsg_ui.c +++ b/src/signMsg_ui.c @@ -141,6 +141,32 @@ void _displayMsgEmpty(ui_callback_fn_t* callback) #endif // HAVE_BAGL } +void _displayMsgIntro(ui_callback_fn_t* callback) +{ + char l1[30] = {0}; + if (ctx->isAscii) { + snprintf(l1, SIZEOF(l1), "Message (ascii)"); + } else { + snprintf(l1, SIZEOF(l1), "Message (hex)"); + } + ASSERT(strlen(l1) + 1 < SIZEOF(l1)); + + char l2[30] = {0}; + snprintf(l2, SIZEOF(l2), "%u bytes", ctx->msgLength); + ASSERT(strlen(l2) + 1 < SIZEOF(l2)); + + #ifdef HAVE_BAGL + ui_displayPaginatedText( + l1, + l2, + callback + ); + #elif defined(HAVE_NBGL) + set_light_confirmation(true); + display_prompt(l1, l2, this_fn, respond_with_user_reject); + #endif // HAVE_BAGL +} + __noinline_due_to_stack__ void _displayMsgFull(ui_callback_fn_t* callback) { @@ -152,7 +178,7 @@ void _displayMsgFull(ui_callback_fn_t* callback) } ASSERT(strlen(l1) + 1 < SIZEOF(l1)); - char l2[2 * MAX_CIP8_MSG_CHUNK_SIZE + 2]; + char l2[200]; if (ctx->isAscii) { ASSERT(ctx->chunkSize + 1 < SIZEOF(l2)); memcpy(l2, ctx->chunk, ctx->chunkSize); @@ -174,20 +200,19 @@ void _displayMsgFull(ui_callback_fn_t* callback) #endif // HAVE_BAGL } +__noinline_due_to_stack__ void _displayMsgChunk(ui_callback_fn_t* callback) { - char l1[30]; + const char* l1 = "Message starts with"; + + char l2[200]; if (ctx->isAscii) { - // TODO do 6 digits fit? - snprintf(l1, SIZEOF(l1), "Msg ascii %u B", ctx->msgLength); + ASSERT(ctx->chunkSize + 1 < SIZEOF(l2)); + memcpy(l2, ctx->chunk, ctx->chunkSize); + l2[ctx->chunkSize] = '\0'; } else { - snprintf(l1, SIZEOF(l1), "Msg hex %u B", ctx->msgLength); + encode_hex(ctx->chunk, ctx->chunkSize, l2, SIZEOF(l2)); } - ASSERT(strlen(l1) + 1 < SIZEOF(l1)); - - char l2[2 * MAX_CIP8_MSG_CHUNK_SIZE + 5]; - size_t len = encode_hex(ctx->chunk, ctx->chunkSize, l2, SIZEOF(l2)); - snprintf(l2 + len, SIZEOF(l2) - len, "..."); ASSERT(strlen(l2) + 1 < SIZEOF(l2)); #ifdef HAVE_BAGL @@ -208,15 +233,22 @@ void signMsg_handleChunk_ui_runStep() TRACE_STACK_USAGE(); ui_callback_fn_t* this_fn = signMsg_handleChunk_ui_runStep; + ASSERT(ctx->receivedChunks == 1); + UI_STEP_BEGIN(ctx->ui_step, this_fn); - UI_STEP(HANDLE_CHUNK_STEP_DISPLAY) { + UI_STEP(HANDLE_CHUNK_STEP_INTRO) { if (ctx->msgLength == 0) { _displayMsgEmpty(this_fn); - } else if (ctx->remainingBytes == 0) { + UI_STEP_JUMP(HANDLE_CHUNK_STEP_RESPOND); + } else { + _displayMsgIntro(this_fn); + } + } + UI_STEP(HANDLE_CHUNK_STEP_DISPLAY) { + if (ctx->remainingBytes == 0) { _displayMsgFull(this_fn); } else { - ASSERT(ctx->hashPayload); _displayMsgChunk(this_fn); } } diff --git a/src/signMsg_ui.h b/src/signMsg_ui.h index 673454f1..ea601ff0 100644 --- a/src/signMsg_ui.h +++ b/src/signMsg_ui.h @@ -21,7 +21,8 @@ void signMsg_handleInit_ui_runStep(); // ============================== CHUNK ============================== enum { - HANDLE_CHUNK_STEP_DISPLAY = 200, + HANDLE_CHUNK_STEP_INTRO = 200, + HANDLE_CHUNK_STEP_DISPLAY, HANDLE_CHUNK_STEP_RESPOND, HANDLE_CHUNK_STEP_INVALID, };