diff --git a/app/src/apdu_handler.c b/app/src/apdu_handler.c index 86a9c30..131625b 100644 --- a/app/src/apdu_handler.c +++ b/app/src/apdu_handler.c @@ -271,6 +271,14 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { handleSignEth(flags, tx, rx); break; } + case INS_SIGN_PERSONAL_MESSAGE: { + CHECK_PIN_VALIDATED() + if (cla != CLA_ETH) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } + handleSignEip191(flags, tx, rx); + break; + } default: THROW(APDU_CODE_INS_NOT_SUPPORTED); } diff --git a/app/src/common/actions.h b/app/src/common/actions.h index a3ea670..d18c41a 100644 --- a/app/src/common/actions.h +++ b/app/src/common/actions.h @@ -22,6 +22,7 @@ #include "coin.h" #include "crypto.h" #include "crypto_eth.h" +#include "eth_eip191.h" #include "tx.h" #include "zxerror.h" @@ -93,7 +94,7 @@ __Z_INLINE void app_sign_eth() { uint16_t replyLen = 0; MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - zxerr_t err = crypto_sign_eth(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength, &replyLen); + zxerr_t err = crypto_sign_eth(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength, &replyLen, false); if (err != zxerr_ok || replyLen == 0) { set_code(G_io_apdu_buffer, 0, APDU_CODE_SIGN_VERIFY_ERROR); @@ -104,6 +105,25 @@ __Z_INLINE void app_sign_eth() { } } +__Z_INLINE void app_sign_eip191() { + const uint8_t *message = tx_get_buffer(); + const uint16_t messageLength = tx_get_buffer_length(); + uint16_t replyLen = 0; + uint8_t hash[32] = {0}; + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + zxerr_t err = eip191_hash_message(message, messageLength, hash); + if (err == zxerr_ok) { + err = crypto_sign_eth(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, hash, 32, &replyLen, true); + } + if (err != zxerr_ok || replyLen == 0) { + set_code(G_io_apdu_buffer, 0, APDU_CODE_SIGN_VERIFY_ERROR); + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); + } else { + set_code(G_io_apdu_buffer, replyLen, APDU_CODE_OK); + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, replyLen + 2); + } +} + __Z_INLINE void app_reject() { MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); set_code(G_io_apdu_buffer, 0, APDU_CODE_COMMAND_NOT_ALLOWED); diff --git a/app/src/evm/apdu_handler_eth.c b/app/src/evm/apdu_handler_eth.c index 75b5c0d..d670004 100644 --- a/app/src/evm/apdu_handler_eth.c +++ b/app/src/evm/apdu_handler_eth.c @@ -21,6 +21,7 @@ #include "coin_eth.h" #include "crypto_eth.h" #include "eth_addr.h" +#include "eth_eip191.h" #include "eth_utils.h" #include "tx_eth.h" #include "view.h" @@ -59,6 +60,67 @@ void extract_eth_path(uint32_t rx, uint32_t offset) { hdPathEth_len = path_len; } +uint32_t bytes_to_read; +bool process_chunk_eip191(__Z_UNUSED volatile uint32_t *tx, uint32_t rx) { + const uint8_t payloadType = G_io_apdu_buffer[OFFSET_PAYLOAD_TYPE]; + if (G_io_apdu_buffer[OFFSET_P2] != 0) { + THROW(APDU_CODE_INVALIDP1P2); + } + if (rx < OFFSET_DATA) { + THROW(APDU_CODE_WRONG_LENGTH); + } + uint8_t *data = &(G_io_apdu_buffer[OFFSET_DATA]); + uint32_t len = rx - OFFSET_DATA; + uint64_t added; + switch (payloadType) { + case P1_ETH_FIRST: + tx_initialize(); + tx_reset(); + extract_eth_path(rx, OFFSET_DATA); + // there is not warranties that the first chunk + // contains the serialized path only; + // so we need to offset the data to point to the first transaction + // byte + uint32_t path_len = sizeof(uint32_t) * hdPathEth_len; + // plus the first offset data containing the path len + data += path_len + 1; + if (len < path_len) { + THROW(APDU_CODE_WRONG_LENGTH); + } + len -= path_len + 1; + // now process the chunk + bytes_to_read = U4BE(data, 0); + bytes_to_read -= len - sizeof(uint32_t); + added = tx_append(data, len); + if (added != len) { + THROW(APDU_CODE_OUTPUT_BUFFER_TOO_SMALL); + } + tx_initialized = true; + if (bytes_to_read == 0) { + tx_initialized = false; + return true; + } + return false; + case P1_ETH_MORE: + if (!tx_initialized) { + THROW(APDU_CODE_TX_NOT_INITIALIZED); + } + // either the entire buffer of the remaining bytes we expect + bytes_to_read -= len; + added = tx_append(data, len); + if (added != len) { + THROW(APDU_CODE_OUTPUT_BUFFER_TOO_SMALL); + } + // check if this chunk was the last one + if (bytes_to_read == 0) { + tx_initialized = false; + return true; + } + return false; + } + THROW(APDU_CODE_INVALIDP1P2); +} + bool process_chunk_eth(__Z_UNUSED volatile uint32_t *tx, uint32_t rx) { const uint8_t payloadType = G_io_apdu_buffer[OFFSET_PAYLOAD_TYPE]; @@ -209,3 +271,21 @@ void handleSignEth(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) view_review_show(REVIEW_TXN); *flags |= IO_ASYNCH_REPLY; } + +void handleSignEip191(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { + zemu_log_stack("handleSignEip191"); + if (!process_chunk_eip191(tx, rx)) { + THROW(APDU_CODE_OK); + } + CHECK_APP_CANARY() + parser_error_t err = eip191_msg_parse(); + if (err == parser_blindsign_required) { + *flags |= IO_ASYNCH_REPLY; + view_blindsign_error_show(); + THROW(APDU_CODE_DATA_INVALID); + } + CHECK_APP_CANARY() + view_review_init(eip191_msg_getItem, eip191_msg_getNumItems, app_sign_eip191); + view_review_show(REVIEW_TXN); + *flags |= IO_ASYNCH_REPLY; +} diff --git a/app/src/evm/apdu_handler_eth.h b/app/src/evm/apdu_handler_eth.h index f9c52fc..110bbd6 100644 --- a/app/src/evm/apdu_handler_eth.h +++ b/app/src/evm/apdu_handler_eth.h @@ -22,7 +22,7 @@ extern "C" { void handleGetAddrEth(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx); void handleSignEth(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx); - +void handleSignEip191(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx); #ifdef __cplusplus } #endif diff --git a/app/src/evm/coin_eth.h b/app/src/evm/coin_eth.h index b9d07a0..b9abd3e 100644 --- a/app/src/evm/coin_eth.h +++ b/app/src/evm/coin_eth.h @@ -43,6 +43,7 @@ extern "C" { #define INS_SIGN_ETH 0x04 #define INS_GET_ADDR_ETH 0x02 +#define INS_SIGN_PERSONAL_MESSAGE 0x08 #define VIEW_ADDRESS_OFFSET_ETH (SECP256K1_PK_LEN + 1 + 1) diff --git a/app/src/evm/crypto_eth.c b/app/src/evm/crypto_eth.c index cbff6cc..5fb2a2e 100644 --- a/app/src/evm/crypto_eth.c +++ b/app/src/evm/crypto_eth.c @@ -139,13 +139,17 @@ zxerr_t _sign(uint8_t *output, uint16_t outputLen, const uint8_t *message, uint1 // Sign an ethereum related transaction zxerr_t crypto_sign_eth(uint8_t *buffer, uint16_t signatureMaxlen, const uint8_t *message, uint16_t messageLen, - uint16_t *sigSize) { + uint16_t *sigSize, bool personal_msg) { if (buffer == NULL || message == NULL || sigSize == NULL || signatureMaxlen < sizeof(signature_t)) { return zxerr_invalid_crypto_settings; } uint8_t message_digest[KECCAK_256_SIZE] = {0}; - CHECK_ZXERR(keccak_digest(message, messageLen, message_digest, KECCAK_256_SIZE)) + if (!personal_msg) { + CHECK_ZXERR(keccak_digest(message, messageLen, message_digest, KECCAK_256_SIZE)) + } else { + MEMCPY(message_digest, message, messageLen); + } unsigned int info = 0; zxerr_t error = _sign(buffer, signatureMaxlen, message_digest, KECCAK_256_SIZE, sigSize, &info); @@ -155,7 +159,7 @@ zxerr_t crypto_sign_eth(uint8_t *buffer, uint16_t signatureMaxlen, const uint8_t // we need to fix V uint8_t v = 0; - error = tx_compute_eth_v(info, &v); + error = tx_compute_eth_v(info, &v, personal_msg); if (error != zxerr_ok) return zxerr_invalid_crypto_settings; diff --git a/app/src/evm/crypto_eth.h b/app/src/evm/crypto_eth.h index 06a2fb9..03321df 100644 --- a/app/src/evm/crypto_eth.h +++ b/app/src/evm/crypto_eth.h @@ -31,7 +31,7 @@ extern uint32_t hdPathEth_len; extern uint8_t flr_chain_code; zxerr_t crypto_fillEthAddress(uint8_t *buffer, uint16_t buffer_len, uint16_t *addrLen); zxerr_t crypto_sign_eth(uint8_t *buffer, uint16_t signatureMaxlen, const uint8_t *message, uint16_t messageLen, - uint16_t *sigSize); + uint16_t *sigSize, bool personal_msg); zxerr_t keccak_digest(const unsigned char *in, unsigned int inLen, unsigned char *out, unsigned int outLen); #ifdef __cplusplus diff --git a/app/src/evm/eth_eip191.c b/app/src/evm/eth_eip191.c new file mode 100644 index 0000000..98886ae --- /dev/null +++ b/app/src/evm/eth_eip191.c @@ -0,0 +1,114 @@ +/******************************************************************************* + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#include "eth_eip191.h" + +#include "actions.h" +#include "apdu_handler_eth.h" +#include "app_main.h" +#include "app_mode.h" +#include "coin_eth.h" +#include "parser_common.h" +#include "zxformat.h" +#include "zxmacros.h" +#if defined(LEDGER_SPECIFIC) +#include "cx.h" +#else +#define CX_SHA256_SIZE 32 +#define CX_RIPEMD160_SIZE 20 +#endif +static const char SIGN_MAGIC[] = + "\x19" + "Ethereum Signed Message:\n"; +zxerr_t eip191_msg_getNumItems(uint8_t *num_items) { + zemu_log_stack("msg_getNumItems"); + *num_items = 2; + return zxerr_ok; +} +zxerr_t eip191_msg_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outVal, uint16_t outValLen, + uint8_t pageIdx, uint8_t *pageCount) { + ZEMU_LOGF(200, "[msg_getItem] %d/%d\n", displayIdx, pageIdx) + MEMZERO(outKey, outKeyLen); + MEMZERO(outVal, outValLen); + snprintf(outKey, outKeyLen, "?"); + snprintf(outVal, outValLen, " "); + *pageCount = 1; + const uint8_t *message = tx_get_buffer() + sizeof(uint32_t); + const uint16_t messageLength = tx_get_buffer_length() - sizeof(uint32_t); + switch (displayIdx) { + case 0: { + snprintf(outKey, outKeyLen, "Sign"); + snprintf(outVal, outValLen, "Personal Message"); + return zxerr_ok; + } + case 1: { + snprintf(outKey, outKeyLen, "Msg hex"); + uint16_t npc = 0; // Non Printable Chars Counter + for (uint16_t i = 0; i < messageLength; i++) { + npc += IS_PRINTABLE(message[i]) ? 0 /* Printable Char */ : 1 /* Non Printable Char */; + } + // msg in hex in case >= than 40% is non printable + // or first char is not printable. + if (messageLength > 0 && (npc * 100) / messageLength >= 40) { + pageStringHex(outVal, outValLen, (const char *)message, messageLength, pageIdx, pageCount); + return zxerr_ok; + } + // print message + snprintf(outKey, outKeyLen, "Msg"); + pageString(outVal, outValLen, (const char *)message, pageIdx, pageCount); + return zxerr_ok; + } + default: + return zxerr_no_data; + } + return zxerr_ok; +} +parser_error_t eip191_msg_parse() { + const uint8_t *message = tx_get_buffer() + sizeof(uint32_t); + const uint16_t messageLength = tx_get_buffer_length() - sizeof(uint32_t); + uint16_t npc = 0; // Non Printable Chars Counter + for (uint16_t i = 0; i < messageLength; i++) { + npc += IS_PRINTABLE(message[i]) ? 0 /* Printable Char */ : 1 /* Non Printable Char */; + } + // msg in hex in case >= than 40% is non printable + // or first char is not printable. + if (messageLength > 0 && (npc * 100) / messageLength >= 40 && !app_mode_blindsign()) { + return parser_blindsign_required; + } else if (messageLength > 0 && (npc * 100) / messageLength < 40) { + app_mode_skip_blindsign_ui(); + } + + return parser_ok; +} +zxerr_t eip191_hash_message(const uint8_t *message, uint16_t messageLen, uint8_t *hash) { + zemu_log_stack("eip191_hash_message"); + if (message == NULL || messageLen == 0) { + return zxerr_unknown; + } + MEMZERO(hash, 32); +#if defined(LEDGER_SPECIFIC) + cx_sha3_t sha3; + CHECK_CX_OK(cx_keccak_init_no_throw(&sha3, 256)); + CHECK_CX_OK(cx_hash_no_throw((cx_hash_t *)&sha3, 0, (uint8_t *)SIGN_MAGIC, sizeof(SIGN_MAGIC) - 1, NULL, 0)); + uint32_t msg_len = U4BE(message, 0); + char len_str[12] = {0}; + uint32_to_str(len_str, sizeof(len_str), msg_len); + CHECK_CX_OK(cx_hash_no_throw((cx_hash_t *)&sha3, 0, (uint8_t *)len_str, strlen(len_str), NULL, 0)); + CHECK_CX_OK( + cx_hash_no_throw((cx_hash_t *)&sha3, CX_LAST, message + sizeof(uint32_t), messageLen - sizeof(uint32_t), hash, 32)); +#endif + zemu_log_stack("eip191_hash_message done"); + return zxerr_ok; +} diff --git a/app/src/evm/eth_eip191.h b/app/src/evm/eth_eip191.h new file mode 100644 index 0000000..a11cfcd --- /dev/null +++ b/app/src/evm/eth_eip191.h @@ -0,0 +1,34 @@ +/******************************************************************************* + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#pragma once +#include +#include + +#include "coin_eth.h" +#include "parser_common.h" +#include "zxerror.h" +#include "zxmacros.h" +#ifdef __cplusplus +extern "C" { +#endif +parser_error_t eip191_msg_parse(); +zxerr_t eip191_msg_getNumItems(uint8_t *num_items); +zxerr_t eip191_msg_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outVal, uint16_t outValLen, + uint8_t pageIdx, uint8_t *pageCount); +zxerr_t eip191_hash_message(const uint8_t *message, uint16_t messageLen, uint8_t *hash); +#ifdef __cplusplus +} +#endif diff --git a/app/src/evm/parser_eth.c b/app/src/evm/parser_eth.c index 5e7e43f..722c3c3 100644 --- a/app/src/evm/parser_eth.c +++ b/app/src/evm/parser_eth.c @@ -69,6 +69,6 @@ parser_error_t parser_getItemEth(const parser_context_t *ctx, uint8_t displayIdx return _getItemEth(ctx, displayIdx, outKey, outKeyLen, outVal, outValLen, pageIdx, pageCount); } -parser_error_t parser_compute_eth_v(parser_context_t *ctx, unsigned int info, uint8_t *v) { - return _computeV(ctx, ð_tx_obj, info, v); +parser_error_t parser_compute_eth_v(parser_context_t *ctx, unsigned int info, uint8_t *v, bool personal_msg) { + return _computeV(ctx, ð_tx_obj, info, v, personal_msg); } diff --git a/app/src/evm/parser_eth.h b/app/src/evm/parser_eth.h index 0e3dd76..23392cf 100644 --- a/app/src/evm/parser_eth.h +++ b/app/src/evm/parser_eth.h @@ -19,6 +19,7 @@ #ifdef __cplusplus extern "C" { #endif +#include #include "parser_impl.h" @@ -38,7 +39,7 @@ parser_error_t parser_getNumItemsEth(const parser_context_t *ctx, uint8_t *num_i parser_error_t parser_getItemEth(const parser_context_t *ctx, uint8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount); -parser_error_t parser_compute_eth_v(parser_context_t *ctx, unsigned int info, uint8_t *v); +parser_error_t parser_compute_eth_v(parser_context_t *ctx, unsigned int info, uint8_t *v, bool personal_msg); #ifdef __cplusplus } #endif diff --git a/app/src/evm/parser_impl_eth.c b/app/src/evm/parser_impl_eth.c index abfebae..5d2b8af 100644 --- a/app/src/evm/parser_impl_eth.c +++ b/app/src/evm/parser_impl_eth.c @@ -37,6 +37,8 @@ eth_tx_t eth_tx_obj; #define DATA_BYTES_TO_PRINT 10 #define TMP_DATA_ARRAY_SIZE 40 #define ERC20_TRANSFER_OFFSET 4 + 12 +#define ETHEREUM_RECOVERY_OFFSET 27 +#define EIP155_V_BASE 35 static parser_error_t readChainID(parser_context_t *ctx, rlp_t *chainId) { if (ctx == NULL || chainId == NULL) { @@ -478,14 +480,20 @@ parser_error_t _getNumItemsEth(uint8_t *numItems) { return parser_ok; } -parser_error_t _computeV(parser_context_t *ctx, eth_tx_t *tx_obj, unsigned int info, uint8_t *v) { +parser_error_t _computeV(parser_context_t *ctx, eth_tx_t *tx_obj, unsigned int info, uint8_t *v, bool personal_msg) { if (ctx == NULL || tx_obj == NULL || v == NULL) { return parser_unexpected_error; } - uint8_t type = eth_tx_obj.tx_type; uint8_t parity = (info & CX_ECCINFO_PARITY_ODD) == 1; + /// No chain id in the transaction use ETHEREUM_RECOVERY_OFFSET + if (personal_msg) { + *v = ETHEREUM_RECOVERY_OFFSET + parity; + return parser_ok; + } + + uint8_t type = eth_tx_obj.tx_type; if (type == eip2930 || type == eip1559) { *v = parity; return parser_ok; @@ -500,7 +508,7 @@ parser_error_t _computeV(parser_context_t *ctx, eth_tx_t *tx_obj, unsigned int i CHECK_ERROR(be_bytes_to_u64(tx_obj->chainId.ptr, tx_obj->chainId.rlpLen, &id)); } - uint32_t cv = 35 + parity; + uint32_t cv = EIP155_V_BASE + parity; cv = saturating_add_u32(cv, (uint32_t)id * 2); *v = (uint8_t)cv; diff --git a/app/src/evm/parser_impl_eth.h b/app/src/evm/parser_impl_eth.h index a24adc8..c97b7c6 100644 --- a/app/src/evm/parser_impl_eth.h +++ b/app/src/evm/parser_impl_eth.h @@ -75,7 +75,7 @@ parser_error_t _getNumItemsEth(uint8_t *numItems); parser_error_t _validateTxEth(); -parser_error_t _computeV(parser_context_t *ctx, eth_tx_t *tx_obj, unsigned int info, uint8_t *v); +parser_error_t _computeV(parser_context_t *ctx, eth_tx_t *tx_obj, unsigned int info, uint8_t *v, bool personal_msg); #ifdef __cplusplus } diff --git a/app/src/evm/tx_eth.c b/app/src/evm/tx_eth.c index 911b830..cc3164d 100644 --- a/app/src/evm/tx_eth.c +++ b/app/src/evm/tx_eth.c @@ -46,8 +46,8 @@ const char *tx_parse_eth(uint8_t *error_code) { return NULL; } -zxerr_t tx_compute_eth_v(unsigned int info, uint8_t *v) { - parser_error_t err = parser_compute_eth_v(&ctx_parsed_tx, info, v); +zxerr_t tx_compute_eth_v(unsigned int info, uint8_t *v, bool personal_msg) { + parser_error_t err = parser_compute_eth_v(&ctx_parsed_tx, info, v, personal_msg); if (err != parser_ok) return zxerr_unknown; diff --git a/app/src/evm/tx_eth.h b/app/src/evm/tx_eth.h index 6d9d323..f8f0092 100644 --- a/app/src/evm/tx_eth.h +++ b/app/src/evm/tx_eth.h @@ -31,4 +31,4 @@ zxerr_t tx_getNumItemsEth(uint8_t *num_items); zxerr_t tx_getItemEth(int8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outValue, uint16_t outValueLen, uint8_t pageIdx, uint8_t *pageCount); -zxerr_t tx_compute_eth_v(unsigned int info, uint8_t *v); +zxerr_t tx_compute_eth_v(unsigned int info, uint8_t *v, bool personal_msg); diff --git a/js b/js index 1a9b852..0d3d3c6 160000 --- a/js +++ b/js @@ -1 +1 @@ -Subproject commit 1a9b8522dcfc3b5abaf1019172341146d2d75885 +Subproject commit 0d3d3c622c9c03c16d4bc906c45aef523c057f71 diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00000.png b/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00000.png new file mode 100644 index 0000000..2f144c9 Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00000.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00001.png b/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00001.png new file mode 100644 index 0000000..f3d0340 Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00001.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00002.png b/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00002.png new file mode 100644 index 0000000..ef4891d Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00002.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00003.png b/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00003.png new file mode 100644 index 0000000..68fabab Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_big_msg/00003.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_msg/00000.png b/tests_zemu/snapshots/fl-eth-personal_sign_msg/00000.png new file mode 100644 index 0000000..2f144c9 Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_msg/00000.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_msg/00001.png b/tests_zemu/snapshots/fl-eth-personal_sign_msg/00001.png new file mode 100644 index 0000000..55cf3a1 Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_msg/00001.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_msg/00002.png b/tests_zemu/snapshots/fl-eth-personal_sign_msg/00002.png new file mode 100644 index 0000000..ef4891d Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_msg/00002.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_msg/00003.png b/tests_zemu/snapshots/fl-eth-personal_sign_msg/00003.png new file mode 100644 index 0000000..68fabab Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_msg/00003.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00000.png b/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00000.png new file mode 100644 index 0000000..acbb161 Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00000.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00001.png b/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00001.png new file mode 100644 index 0000000..8abcfd0 Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00001.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00002.png b/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00002.png new file mode 100644 index 0000000..476a3f8 Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00002.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00003.png b/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00003.png new file mode 100644 index 0000000..67c89d1 Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00003.png differ diff --git a/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00004.png b/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00004.png new file mode 100644 index 0000000..68fabab Binary files /dev/null and b/tests_zemu/snapshots/fl-eth-personal_sign_non_printable_msg/00004.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00000.png b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00000.png new file mode 100644 index 0000000..8418b80 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00000.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00001.png b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00001.png new file mode 100644 index 0000000..6b9aa66 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00001.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00002.png b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00002.png new file mode 100644 index 0000000..5a9cfbd Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00002.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00003.png b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00003.png new file mode 100644 index 0000000..ae65823 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00003.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00004.png b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00004.png new file mode 100644 index 0000000..006c26a Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00004.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00005.png b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00005.png new file mode 100644 index 0000000..a0d6c57 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_big_msg/00005.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_msg/00000.png b/tests_zemu/snapshots/s-eth-personal_sign_msg/00000.png new file mode 100644 index 0000000..8418b80 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_msg/00000.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_msg/00001.png b/tests_zemu/snapshots/s-eth-personal_sign_msg/00001.png new file mode 100644 index 0000000..d54190e Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_msg/00001.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_msg/00002.png b/tests_zemu/snapshots/s-eth-personal_sign_msg/00002.png new file mode 100644 index 0000000..006c26a Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_msg/00002.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_msg/00003.png b/tests_zemu/snapshots/s-eth-personal_sign_msg/00003.png new file mode 100644 index 0000000..a0d6c57 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_msg/00003.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00000.png b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00000.png new file mode 100644 index 0000000..be5b449 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00000.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00001.png b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00001.png new file mode 100644 index 0000000..72032ef Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00001.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00002.png b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00002.png new file mode 100644 index 0000000..5664a98 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00002.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00003.png b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00003.png new file mode 100644 index 0000000..28aca92 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00003.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00004.png b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00004.png new file mode 100644 index 0000000..5439e9f Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00004.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00005.png b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00005.png new file mode 100644 index 0000000..f015319 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00005.png differ diff --git a/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00006.png b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00006.png new file mode 100644 index 0000000..a0d6c57 Binary files /dev/null and b/tests_zemu/snapshots/s-eth-personal_sign_non_printable_msg/00006.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00000.png b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00000.png new file mode 100644 index 0000000..fe99275 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00000.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00001.png b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00001.png new file mode 100644 index 0000000..78130d7 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00001.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00002.png b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00002.png new file mode 100644 index 0000000..f6aa3a4 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00002.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00003.png b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00003.png new file mode 100644 index 0000000..5592238 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00003.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00004.png b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00004.png new file mode 100644 index 0000000..1e4be69 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00004.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00005.png b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00005.png new file mode 100644 index 0000000..1a4c3b9 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_big_msg/00005.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_msg/00000.png b/tests_zemu/snapshots/sp-eth-personal_sign_msg/00000.png new file mode 100644 index 0000000..fe99275 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_msg/00000.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_msg/00001.png b/tests_zemu/snapshots/sp-eth-personal_sign_msg/00001.png new file mode 100644 index 0000000..78130d7 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_msg/00001.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_msg/00002.png b/tests_zemu/snapshots/sp-eth-personal_sign_msg/00002.png new file mode 100644 index 0000000..995b787 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_msg/00002.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_msg/00003.png b/tests_zemu/snapshots/sp-eth-personal_sign_msg/00003.png new file mode 100644 index 0000000..1e4be69 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_msg/00003.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_msg/00004.png b/tests_zemu/snapshots/sp-eth-personal_sign_msg/00004.png new file mode 100644 index 0000000..1a4c3b9 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_msg/00004.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00000.png b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00000.png new file mode 100644 index 0000000..e65c5e9 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00000.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00001.png b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00001.png new file mode 100644 index 0000000..01fe7bc Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00001.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00002.png b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00002.png new file mode 100644 index 0000000..87ba58f Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00002.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00003.png b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00003.png new file mode 100644 index 0000000..78130d7 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00003.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00004.png b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00004.png new file mode 100644 index 0000000..bdb0922 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00004.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00005.png b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00005.png new file mode 100644 index 0000000..542e61f Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00005.png differ diff --git a/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00006.png b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00006.png new file mode 100644 index 0000000..1a4c3b9 Binary files /dev/null and b/tests_zemu/snapshots/sp-eth-personal_sign_non_printable_msg/00006.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00000.png b/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00000.png new file mode 100644 index 0000000..20e4c11 Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00000.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00001.png b/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00001.png new file mode 100644 index 0000000..8a1a77e Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00001.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00002.png b/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00002.png new file mode 100644 index 0000000..54e33fa Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00002.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00003.png b/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00003.png new file mode 100644 index 0000000..19f096e Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_big_msg/00003.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_msg/00000.png b/tests_zemu/snapshots/st-eth-personal_sign_msg/00000.png new file mode 100644 index 0000000..20e4c11 Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_msg/00000.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_msg/00001.png b/tests_zemu/snapshots/st-eth-personal_sign_msg/00001.png new file mode 100644 index 0000000..8b8e620 Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_msg/00001.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_msg/00002.png b/tests_zemu/snapshots/st-eth-personal_sign_msg/00002.png new file mode 100644 index 0000000..54e33fa Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_msg/00002.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_msg/00003.png b/tests_zemu/snapshots/st-eth-personal_sign_msg/00003.png new file mode 100644 index 0000000..19f096e Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_msg/00003.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00000.png b/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00000.png new file mode 100644 index 0000000..9696ae1 Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00000.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00001.png b/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00001.png new file mode 100644 index 0000000..55efb4a Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00001.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00002.png b/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00002.png new file mode 100644 index 0000000..23f58ad Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00002.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00003.png b/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00003.png new file mode 100644 index 0000000..87a9073 Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00003.png differ diff --git a/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00004.png b/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00004.png new file mode 100644 index 0000000..19f096e Binary files /dev/null and b/tests_zemu/snapshots/st-eth-personal_sign_non_printable_msg/00004.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00000.png b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00000.png new file mode 100644 index 0000000..fe99275 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00000.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00001.png b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00001.png new file mode 100644 index 0000000..78130d7 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00001.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00002.png b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00002.png new file mode 100644 index 0000000..f6aa3a4 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00002.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00003.png b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00003.png new file mode 100644 index 0000000..5592238 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00003.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00004.png b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00004.png new file mode 100644 index 0000000..1e4be69 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00004.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00005.png b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00005.png new file mode 100644 index 0000000..1a4c3b9 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_big_msg/00005.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_msg/00000.png b/tests_zemu/snapshots/x-eth-personal_sign_msg/00000.png new file mode 100644 index 0000000..fe99275 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_msg/00000.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_msg/00001.png b/tests_zemu/snapshots/x-eth-personal_sign_msg/00001.png new file mode 100644 index 0000000..78130d7 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_msg/00001.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_msg/00002.png b/tests_zemu/snapshots/x-eth-personal_sign_msg/00002.png new file mode 100644 index 0000000..995b787 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_msg/00002.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_msg/00003.png b/tests_zemu/snapshots/x-eth-personal_sign_msg/00003.png new file mode 100644 index 0000000..1e4be69 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_msg/00003.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_msg/00004.png b/tests_zemu/snapshots/x-eth-personal_sign_msg/00004.png new file mode 100644 index 0000000..1a4c3b9 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_msg/00004.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00000.png b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00000.png new file mode 100644 index 0000000..e65c5e9 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00000.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00001.png b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00001.png new file mode 100644 index 0000000..01fe7bc Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00001.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00002.png b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00002.png new file mode 100644 index 0000000..87ba58f Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00002.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00003.png b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00003.png new file mode 100644 index 0000000..78130d7 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00003.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00004.png b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00004.png new file mode 100644 index 0000000..bdb0922 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00004.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00005.png b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00005.png new file mode 100644 index 0000000..542e61f Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00005.png differ diff --git a/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00006.png b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00006.png new file mode 100644 index 0000000..1a4c3b9 Binary files /dev/null and b/tests_zemu/snapshots/x-eth-personal_sign_non_printable_msg/00006.png differ diff --git a/tests_zemu/tests/eip191.test.ts b/tests_zemu/tests/eip191.test.ts new file mode 100644 index 0000000..b635e12 --- /dev/null +++ b/tests_zemu/tests/eip191.test.ts @@ -0,0 +1,73 @@ +/** ****************************************************************************** + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +import Zemu, { ButtonKind, isTouchDevice } from '@zondax/zemu' +import { FlareApp } from '@zondax/ledger-flare' +import { ETH_PATH, EXPECTED_ETH_ADDRESS, EXPECTED_ETH_PK, defaultOptions, models } from './common' +import { ec } from 'elliptic' +jest.setTimeout(90000) +const sha3 = require('js-sha3') +const SIGN_TEST_DATA = [ + { + name: 'personal_sign_msg', + message: Buffer.from('Hello World!', 'utf8'), + blind: false, + }, + { + name: 'personal_sign_big_msg', + message: Buffer.from('Just a big dummy message to be sign. To test if ew are parsing the chunks in the right way. By: Zondax', 'utf8'), + blind: false, + }, + { + name: 'personal_sign_non_printable_msg', + message: Buffer.from('\x00\x00\x00\x00\x00zx', 'utf8'), + blind: true, + }, +] +describe.each(models)('EIP191', function (m) { + test.concurrent.each(SIGN_TEST_DATA)('sign transaction: $name', async function (data) { + const sim = new Zemu(m.path) + try { + await sim.start({ ...defaultOptions, model: m.name }) + const app = new FlareApp(sim.getTransport()) + const msgData = data.message + + if (data.blind) { + await sim.toggleBlindSigning() + } + // do not wait here.. + const signatureRequest = app.signPersonalMessage(ETH_PATH, msgData.toString('hex')) + // Wait until we are not in the main menu + await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) + await sim.compareSnapshotsAndApprove('.', `${m.prefix.toLowerCase()}-eth-${data.name}`, true, 0, 1500, data.blind) + let resp = await signatureRequest + console.log(resp) + const header = Buffer.from('\x19Ethereum Signed Message:\n', 'utf8') + const msgLengthString = String(msgData.length) + const msg = Buffer.concat([header, Buffer.from(msgLengthString, 'utf8'), msgData]) + const msgHash = sha3.keccak256(msg) + const signature_obj = { + r: Buffer.from(resp.r, 'hex'), + s: Buffer.from(resp.s, 'hex'), + } + // Verify signature + const EC = new ec('secp256k1') + const signatureOK = EC.verify(msgHash, signature_obj, Buffer.from(EXPECTED_ETH_PK, 'hex'), 'hex') + expect(signatureOK).toEqual(true) + } finally { + await sim.close() + } + }) +})