EIP-191 clear signing
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
#include "shared_context.h"
|
#include "shared_context.h"
|
||||||
#include "apdu_constants.h"
|
#include "apdu_constants.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@@ -7,12 +8,108 @@ static const char SIGN_MAGIC[] =
|
|||||||
"\x19"
|
"\x19"
|
||||||
"Ethereum Signed Message:\n";
|
"Ethereum Signed Message:\n";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a given character is a "special" displayable ASCII character
|
||||||
|
*
|
||||||
|
* @param[in] c character we're checking
|
||||||
|
* @return wether the character is special or not
|
||||||
|
*/
|
||||||
|
static inline bool is_char_special(char c) {
|
||||||
|
return ((c >= '\b') && (c <= '\r'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a given data is made of ASCII characters
|
||||||
|
*
|
||||||
|
* @param[in] data the input data
|
||||||
|
* @param[in] the length of the input data
|
||||||
|
* @return wether the data is fully ASCII or not
|
||||||
|
*/
|
||||||
|
static bool is_data_ascii(const uint8_t *const data, uint8_t length) {
|
||||||
|
for (uint8_t idx = 0; idx < length; ++idx) {
|
||||||
|
if (!is_char_special(data[idx]) && ((data[idx] < 0x20) || (data[idx] > 0x7e))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize value string that will be displayed in the UX STEP
|
||||||
|
*
|
||||||
|
* @param[in] if the value is ASCII
|
||||||
|
*/
|
||||||
|
static void init_value_str(bool is_ascii) {
|
||||||
|
if (is_ascii) {
|
||||||
|
strings.tmp.tmp[0] = '\0'; // init string as empty
|
||||||
|
} else {
|
||||||
|
strcpy(strings.tmp.tmp, "0x"); // will display the hex bytes instead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the global UI string variable by formatting & appending the new data to it
|
||||||
|
*
|
||||||
|
* @param[in] data the input data
|
||||||
|
* @param[in] length the data length
|
||||||
|
* @param[in] is_ascii wether the data is ASCII or not
|
||||||
|
*/
|
||||||
|
static void feed_value_str(const uint8_t *const data, uint8_t length, bool is_ascii) {
|
||||||
|
uint16_t value_strlen = strlen(strings.tmp.tmp);
|
||||||
|
|
||||||
|
if ((value_strlen + 1) < sizeof(strings.tmp.tmp)) {
|
||||||
|
if (is_ascii) {
|
||||||
|
uint8_t src_idx = 0;
|
||||||
|
uint16_t dst_idx = value_strlen;
|
||||||
|
bool prev_is_special = false;
|
||||||
|
|
||||||
|
while ((src_idx < length) && (dst_idx < sizeof(strings.tmp.tmp))) {
|
||||||
|
if (prev_is_special) {
|
||||||
|
if (!is_char_special(data[src_idx])) {
|
||||||
|
prev_is_special = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (is_char_special(data[src_idx])) {
|
||||||
|
prev_is_special = true;
|
||||||
|
strings.tmp.tmp[dst_idx] = ' ';
|
||||||
|
dst_idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!is_char_special(data[src_idx])) {
|
||||||
|
strings.tmp.tmp[dst_idx] = data[src_idx];
|
||||||
|
dst_idx += 1;
|
||||||
|
}
|
||||||
|
src_idx += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst_idx < sizeof(strings.tmp.tmp)) {
|
||||||
|
strings.tmp.tmp[dst_idx] = '\0';
|
||||||
|
} else {
|
||||||
|
const char marker[] = "...";
|
||||||
|
|
||||||
|
memcpy(strings.tmp.tmp + sizeof(strings.tmp.tmp) - sizeof(marker),
|
||||||
|
marker,
|
||||||
|
sizeof(marker));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
snprintf(strings.tmp.tmp + value_strlen,
|
||||||
|
sizeof(strings.tmp.tmp) - value_strlen,
|
||||||
|
"%.*H",
|
||||||
|
length,
|
||||||
|
data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handleSignPersonalMessage(uint8_t p1,
|
void handleSignPersonalMessage(uint8_t p1,
|
||||||
uint8_t p2,
|
uint8_t p2,
|
||||||
uint8_t *workBuffer,
|
uint8_t *workBuffer,
|
||||||
uint16_t dataLength,
|
uint16_t dataLength,
|
||||||
unsigned int *flags,
|
unsigned int *flags,
|
||||||
unsigned int *tx) {
|
unsigned int *tx) {
|
||||||
|
// Point to this unused global variable for persistency
|
||||||
|
bool *is_ascii = (bool *) &strings.tmp.tmp2[0];
|
||||||
|
|
||||||
UNUSED(tx);
|
UNUSED(tx);
|
||||||
uint8_t hashMessage[INT256_LENGTH];
|
uint8_t hashMessage[INT256_LENGTH];
|
||||||
if (p1 == P1_FIRST) {
|
if (p1 == P1_FIRST) {
|
||||||
@@ -29,6 +126,7 @@ void handleSignPersonalMessage(uint8_t p1,
|
|||||||
reset_app_context();
|
reset_app_context();
|
||||||
}
|
}
|
||||||
appState = APP_STATE_SIGNING_MESSAGE;
|
appState = APP_STATE_SIGNING_MESSAGE;
|
||||||
|
|
||||||
tmpCtx.messageSigningContext.pathLength = workBuffer[0];
|
tmpCtx.messageSigningContext.pathLength = workBuffer[0];
|
||||||
if ((tmpCtx.messageSigningContext.pathLength < 0x01) ||
|
if ((tmpCtx.messageSigningContext.pathLength < 0x01) ||
|
||||||
(tmpCtx.messageSigningContext.pathLength > MAX_BIP32_PATH)) {
|
(tmpCtx.messageSigningContext.pathLength > MAX_BIP32_PATH)) {
|
||||||
@@ -38,21 +136,21 @@ void handleSignPersonalMessage(uint8_t p1,
|
|||||||
workBuffer++;
|
workBuffer++;
|
||||||
dataLength--;
|
dataLength--;
|
||||||
for (i = 0; i < tmpCtx.messageSigningContext.pathLength; i++) {
|
for (i = 0; i < tmpCtx.messageSigningContext.pathLength; i++) {
|
||||||
if (dataLength < 4) {
|
if (dataLength < sizeof(uint32_t)) {
|
||||||
PRINTF("Invalid data\n");
|
PRINTF("Invalid data\n");
|
||||||
THROW(0x6a80);
|
THROW(0x6a80);
|
||||||
}
|
}
|
||||||
tmpCtx.messageSigningContext.bip32Path[i] = U4BE(workBuffer, 0);
|
tmpCtx.messageSigningContext.bip32Path[i] = U4BE(workBuffer, 0);
|
||||||
workBuffer += 4;
|
workBuffer += sizeof(uint32_t);
|
||||||
dataLength -= 4;
|
dataLength -= sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
if (dataLength < 4) {
|
if (dataLength < sizeof(uint32_t)) {
|
||||||
PRINTF("Invalid data\n");
|
PRINTF("Invalid data\n");
|
||||||
THROW(0x6a80);
|
THROW(0x6a80);
|
||||||
}
|
}
|
||||||
tmpCtx.messageSigningContext.remainingLength = U4BE(workBuffer, 0);
|
tmpCtx.messageSigningContext.remainingLength = U4BE(workBuffer, 0);
|
||||||
workBuffer += 4;
|
workBuffer += sizeof(uint32_t);
|
||||||
dataLength -= 4;
|
dataLength -= sizeof(uint32_t);
|
||||||
// Initialize message header + length
|
// Initialize message header + length
|
||||||
cx_keccak_init(&global_sha3, 256);
|
cx_keccak_init(&global_sha3, 256);
|
||||||
cx_hash((cx_hash_t *) &global_sha3,
|
cx_hash((cx_hash_t *) &global_sha3,
|
||||||
@@ -71,6 +169,10 @@ void handleSignPersonalMessage(uint8_t p1,
|
|||||||
tmp[pos] = '\0';
|
tmp[pos] = '\0';
|
||||||
cx_hash((cx_hash_t *) &global_sha3, 0, (uint8_t *) tmp, pos, NULL, 0);
|
cx_hash((cx_hash_t *) &global_sha3, 0, (uint8_t *) tmp, pos, NULL, 0);
|
||||||
cx_sha256_init(&tmpContent.sha2);
|
cx_sha256_init(&tmpContent.sha2);
|
||||||
|
|
||||||
|
*is_ascii = is_data_ascii(workBuffer, dataLength);
|
||||||
|
init_value_str(*is_ascii);
|
||||||
|
|
||||||
} else if (p1 != P1_MORE) {
|
} else if (p1 != P1_MORE) {
|
||||||
THROW(0x6B00);
|
THROW(0x6B00);
|
||||||
}
|
}
|
||||||
@@ -84,9 +186,13 @@ void handleSignPersonalMessage(uint8_t p1,
|
|||||||
if (dataLength > tmpCtx.messageSigningContext.remainingLength) {
|
if (dataLength > tmpCtx.messageSigningContext.remainingLength) {
|
||||||
THROW(0x6A80);
|
THROW(0x6A80);
|
||||||
}
|
}
|
||||||
|
|
||||||
cx_hash((cx_hash_t *) &global_sha3, 0, workBuffer, dataLength, NULL, 0);
|
cx_hash((cx_hash_t *) &global_sha3, 0, workBuffer, dataLength, NULL, 0);
|
||||||
cx_hash((cx_hash_t *) &tmpContent.sha2, 0, workBuffer, dataLength, NULL, 0);
|
cx_hash((cx_hash_t *) &tmpContent.sha2, 0, workBuffer, dataLength, NULL, 0);
|
||||||
tmpCtx.messageSigningContext.remainingLength -= dataLength;
|
tmpCtx.messageSigningContext.remainingLength -= dataLength;
|
||||||
|
|
||||||
|
feed_value_str(workBuffer, dataLength, *is_ascii);
|
||||||
|
|
||||||
if (tmpCtx.messageSigningContext.remainingLength == 0) {
|
if (tmpCtx.messageSigningContext.remainingLength == 0) {
|
||||||
cx_hash((cx_hash_t *) &global_sha3,
|
cx_hash((cx_hash_t *) &global_sha3,
|
||||||
CX_LAST,
|
CX_LAST,
|
||||||
@@ -95,11 +201,6 @@ void handleSignPersonalMessage(uint8_t p1,
|
|||||||
tmpCtx.messageSigningContext.hash,
|
tmpCtx.messageSigningContext.hash,
|
||||||
32);
|
32);
|
||||||
cx_hash((cx_hash_t *) &tmpContent.sha2, CX_LAST, workBuffer, 0, hashMessage, 32);
|
cx_hash((cx_hash_t *) &tmpContent.sha2, CX_LAST, workBuffer, 0, hashMessage, 32);
|
||||||
snprintf(strings.tmp.tmp,
|
|
||||||
sizeof(strings.tmp.tmp),
|
|
||||||
"%.*H",
|
|
||||||
sizeof(hashMessage),
|
|
||||||
hashMessage);
|
|
||||||
|
|
||||||
#ifdef NO_CONSENT
|
#ifdef NO_CONSENT
|
||||||
io_seproxyhal_touch_signMessage_ok(NULL);
|
io_seproxyhal_touch_signMessage_ok(NULL);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ UX_STEP_NOCB(
|
|||||||
ux_sign_flow_2_step,
|
ux_sign_flow_2_step,
|
||||||
bnnn_paging,
|
bnnn_paging,
|
||||||
{
|
{
|
||||||
.title = "Message hash",
|
.title = "Message",
|
||||||
.text = strings.tmp.tmp,
|
.text = strings.tmp.tmp,
|
||||||
});
|
});
|
||||||
UX_STEP_CB(
|
UX_STEP_CB(
|
||||||
|
|||||||
Reference in New Issue
Block a user