From 98ca4e48f1e7d5237d6e68ef7ba8295d7f489773 Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Mon, 11 Sep 2023 22:43:47 -0600 Subject: [PATCH 1/9] Implement Message Signing --- doc/COMMANDS.md | 30 ++++++++ src/apdu/dispatcher.c | 8 +++ src/constants.h | 7 ++ src/crypto.c | 37 +++++++++- src/crypto.h | 13 +++- src/handler/sign_msg.c | 86 +++++++++++++++++++++++ src/handler/sign_msg.h | 42 +++++++++++ src/handler/sign_tx.c | 2 +- src/helper/send_reponse.c | 18 +++++ src/helper/send_response.h | 10 +++ src/personal_message.c | 76 ++++++++++++++++++++ src/personal_message.h | 27 ++++++++ src/types.h | 23 +++++-- src/ui/action/validate.c | 19 ++++- src/ui/action/validate.h | 9 +++ src/ui/bagl_display.c | 54 +++++++++++++++ src/ui/display.h | 8 +++ unit-tests/CMakeLists.txt | 4 ++ unit-tests/test_personal_message.c | 107 +++++++++++++++++++++++++++++ 19 files changed, 572 insertions(+), 8 deletions(-) create mode 100644 src/handler/sign_msg.c create mode 100644 src/handler/sign_msg.h create mode 100644 src/personal_message.c create mode 100644 src/personal_message.h create mode 100644 unit-tests/test_personal_message.c diff --git a/doc/COMMANDS.md b/doc/COMMANDS.md index 334ad62..e9368c9 100644 --- a/doc/COMMANDS.md +++ b/doc/COMMANDS.md @@ -121,6 +121,36 @@ Transactions signed with ECDSA are currently not supported. \* While `has_more` is non-zero, you can ask for the next signature by sending another APDU back +## SIGN_MESSAGE + +### Command + +| CLA | INS | P1 | P2 | Lc | CData | +| --- | --- | --- | --- | --- | --- | +| 0xE0 | 0x07 | 0x00 | 0x00 | var | `address_type (1)` \|\| `address_index (4)` \|\|
`message_len (1 bytes)` \|\| `message (var bytes)` | + +| CData Part | Description | +| --- | --- | +| `address_type` | Either `00` for Receive Address or `01` for Change Address | +| `address_index` | Any value from `00000000` to `11111111` | +| `message_len` | How long the message is. Must be a value from `1` to `128`, inclusive | +| `message` | The message to sign | + +### Response + +| Length
(bytes) | SW | RData | +| --- | --- | --- | +| var | 0x9000 | See Response Breakdown | + +#### Response Breakdown + +| Data | Description | +| --- | --- | +| `len(sig)` | The length of the signature. Always 64 bytes with Schnorr | +| `sig` | The Schnorr signature | +| `len(message_hash)` | The length of the message hash. Always 32 bytes | +| `message_hash` | The hash that was signed. | + ## Status Words | SW | SW name | Description | diff --git a/src/apdu/dispatcher.c b/src/apdu/dispatcher.c index 771049f..fc1ceeb 100644 --- a/src/apdu/dispatcher.c +++ b/src/apdu/dispatcher.c @@ -35,6 +35,7 @@ #include "../handler/get_app_name.h" #include "../handler/get_public_key.h" #include "../handler/sign_tx.h" +#include "../handler/sign_msg.h" #ifdef HAVE_DEBUG_APDU #include "../handler/debug.h" @@ -92,6 +93,13 @@ int apdu_dispatcher(const command_t *cmd) { buf.offset = 0; return handler_sign_tx(&buf, cmd->p1, (bool) (cmd->p2 & P2_MORE)); + case SIGN_MESSAGE: + + buf.ptr = cmd->data; + buf.size = cmd->lc; + buf.offset = 0; + + return handler_sign_msg(&buf); #ifdef HAVE_DEBUG_APDU case DEBUG_APDU: return handler_debug(cmd->p1); diff --git a/src/constants.h b/src/constants.h index 4b6a667..9f28ff4 100644 --- a/src/constants.h +++ b/src/constants.h @@ -48,6 +48,11 @@ */ #define MAX_TRANSACTION_LEN 128 +/** + * Maximum message length (bytes) + */ +#define MAX_MESSAGE_LEN 128 + /** * Maximum signature length (bytes). * Schnorr signatures only have 64 bytes @@ -70,4 +75,6 @@ */ #define SIGNING_KEY "TransactionSigningHash" +#define MESSAGE_SIGNING_KEY "PersonalMessageSigningHash" + #define MAX_OUTPUT_COUNT 2 diff --git a/src/crypto.c b/src/crypto.c index ab22a19..48731b4 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -31,6 +31,7 @@ #include "globals.h" #include "sighash.h" +#include "personal_message.h" bool crypto_validate_public_key(const uint32_t *bip32_path, uint8_t bip32_path_len, @@ -54,7 +55,7 @@ bool crypto_validate_public_key(const uint32_t *bip32_path, return memcmp(raw_pubkey + 1, compressed_public_key, 32) == 0; } -int crypto_sign_message(void) { +int crypto_sign_transaction(void) { cx_ecfp_private_key_t private_key = {0}; cx_ecfp_public_key_t public_key = {0}; uint8_t chain_code[32] = {0}; @@ -117,3 +118,37 @@ int crypto_sign_message(void) { return error; } + +int crypto_sign_personal_message(void) { + hash_personal_message(G_context.msg_info.message, + G_context.msg_info.message_len, + G_context.msg_info.message_hash); + + cx_ecfp_private_key_t private_key = {0}; + uint8_t chain_code[32] = {0}; + + int error = bip32_derive_init_privkey_256(CX_CURVE_256K1, + G_context.bip32_path, + G_context.bip32_path_len, + &private_key, + chain_code); + + BEGIN_TRY { + TRY { + size_t sig_len = sizeof(G_context.tx_info.signature); + error = cx_ecschnorr_sign_no_throw(&private_key, + CX_ECSCHNORR_BIP0340 | CX_RND_TRNG, + CX_SHA256, + G_context.msg_info.message_hash, + sizeof(G_context.msg_info.message_hash), + G_context.msg_info.signature, + &sig_len); + } + FINALLY { + explicit_bzero(&private_key, sizeof(private_key)); + } + } + END_TRY; + + return error; +} diff --git a/src/crypto.h b/src/crypto.h index ff05f0a..aa89ed1 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -37,7 +37,7 @@ * @return 0 on success, error number otherwise. * */ -int crypto_sign_message(void); +int crypto_sign_transaction(void); /** * Checks if the compressed public key matches the @@ -56,3 +56,14 @@ int crypto_sign_message(void); bool crypto_validate_public_key(const uint32_t *bip32_path, uint8_t bip32_path_len, uint8_t compressed_public_key[static 32]); + +/** + * Sign personal message hash in global context. + * + * @see G_context.bip32_path, + * G_context.msg_info.signature. + * + * @return 0 on success, error number otherwise. + * + */ +int crypto_sign_personal_message(void); \ No newline at end of file diff --git a/src/handler/sign_msg.c b/src/handler/sign_msg.c new file mode 100644 index 0000000..cc4a51e --- /dev/null +++ b/src/handler/sign_msg.c @@ -0,0 +1,86 @@ +/***************************************************************************** + * MIT License + * + * Copyright (c) 2023 coderofstuff + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ +#include // uint*_t +#include // memset, explicit_bzero + +#include "types.h" +#include "buffer.h" +#include "./globals.h" +#include "./sign_msg.h" +#include "../sw.h" +#include "../ui/display.h" +#include "../helper/send_response.h" + +/** + * Handler for SIGN_MESSAGE command. If successfully parse BIP32 path + * and message, sign the message and send APDU response. + * + * @see G_context.bip32_path, G_context.msg_info + * + * @param[in,out] cdata + * Command data with BIP32 path and raw message. + * + * @return zero or positive integer if success, negative integer otherwise. + * + */ +int handler_sign_msg(buffer_t *cdata) { + explicit_bzero(&G_context, sizeof(G_context)); + G_context.req_type = CONFIRM_MESSAGE; + G_context.state = STATE_NONE; + + if (!buffer_read_u8(cdata, &G_context.msg_info.address_type)) { + return io_send_sw(SW_WRONG_DATA_LENGTH); + } + + if (!buffer_read_u32(cdata, &G_context.msg_info.address_index, BE)) { + return io_send_sw(SW_WRONG_DATA_LENGTH); + } + + uint8_t message_len = 0; + if (!buffer_read_u8(cdata, &message_len)) { + return io_send_sw(SW_WRONG_DATA_LENGTH); + } + + G_context.msg_info.message_len = (size_t) message_len; + + if (!buffer_can_read(cdata, G_context.msg_info.message_len)) { + return io_send_sw(SW_WRONG_DATA_LENGTH); + } + + memcpy(G_context.msg_info.message, cdata->ptr + cdata->offset, G_context.msg_info.message_len); + + if (!buffer_seek_cur(cdata, G_context.msg_info.message_len)) { + return io_send_sw(SW_WRONG_DATA_LENGTH); + } + + G_context.bip32_path[0] = 0x8000002C; + G_context.bip32_path[1] = 0x8001b207; + G_context.bip32_path[2] = 0x80000000; + G_context.bip32_path[3] = (uint32_t)(G_context.msg_info.address_type); + G_context.bip32_path[4] = G_context.msg_info.address_index; + + G_context.bip32_path_len = 5; + + return ui_display_message(); +} \ No newline at end of file diff --git a/src/handler/sign_msg.h b/src/handler/sign_msg.h new file mode 100644 index 0000000..9159a7f --- /dev/null +++ b/src/handler/sign_msg.h @@ -0,0 +1,42 @@ +/***************************************************************************** + * MIT License + * + * Copyright (c) 2023 coderofstuff + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ +#pragma once + +#include // uint*_t + +#include "buffer.h" + +/** + * Handler for SIGN_MESSAGE command. If successfully parse BIP32 path + * and message, sign the message and send APDU response. + * + * @see G_context.bip32_path, G_context.msg_info + * + * @param[in,out] cdata + * Command data with BIP32 path and raw message. + * + * @return zero or positive integer if success, negative integer otherwise. + * + */ +int handler_sign_msg(buffer_t *cdata); diff --git a/src/handler/sign_tx.c b/src/handler/sign_tx.c index 7956cbc..36139ac 100644 --- a/src/handler/sign_tx.c +++ b/src/handler/sign_tx.c @@ -43,7 +43,7 @@ #include "../helper/send_response.h" static int sign_input_and_send() { - int error = crypto_sign_message(); + int error = crypto_sign_transaction(); if (error != 0) { G_context.state = STATE_NONE; io_send_sw(error); diff --git a/src/helper/send_reponse.c b/src/helper/send_reponse.c index 2d8ba24..8fe51dc 100644 --- a/src/helper/send_reponse.c +++ b/src/helper/send_reponse.c @@ -68,3 +68,21 @@ int helper_send_response_sig() { return io_send_response_pointer(resp, offset, SW_OK); } + +int helper_send_response_personal_message_sig() { + uint8_t resp[3 + MAX_DER_SIG_LEN + 34] = {0}; + size_t offset = 0; + + // len(sig) -> 1 byte + resp[offset++] = MAX_DER_SIG_LEN; + // sig -> 64 bytes + memmove(resp + offset, G_context.msg_info.signature, MAX_DER_SIG_LEN); + offset += MAX_DER_SIG_LEN; + // len(sighash) -> 1 byte + resp[offset++] = sizeof(G_context.msg_info.message_hash); + // sighash -> 32 bytes + memmove(resp + offset, G_context.msg_info.message_hash, sizeof(G_context.msg_info.message_hash)); + offset += sizeof(G_context.msg_info.message_hash); + + return io_send_response_pointer(resp, offset, SW_OK); +} diff --git a/src/helper/send_response.h b/src/helper/send_response.h index 78155dc..49b9695 100644 --- a/src/helper/send_response.h +++ b/src/helper/send_response.h @@ -60,3 +60,13 @@ int helper_send_response_pubkey(void); * */ int helper_send_response_sig(void); + +/** + * Helper to send APDU response with personal message signature + * response = MAX_DER_SIG_LEN (1) || + * G_context.tx_info.signature (MAX_DER_SIG_LEN) + * + * @return zero or positive integer if success, -1 otherwise. + * + */ +int helper_send_response_personal_message_sig(void); diff --git a/src/personal_message.c b/src/personal_message.c new file mode 100644 index 0000000..1c61569 --- /dev/null +++ b/src/personal_message.c @@ -0,0 +1,76 @@ +/***************************************************************************** + * MIT License + * + * Copyright (c) 2023 coderofstuff + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ +#include +#include + +// #include "cx.h" + +#include "constants.h" +#include "./import/blake2-impl.h" +#include "./import/blake2b.h" +#include "./personal_message.h" + +// #include "globals.h" + +static int hash_init(blake2b_state* hash, size_t size, uint8_t* key, size_t key_len) { + if (key == NULL && key_len != 0) { + goto err; + } + + if (size % 8 != 0 || size < 8 || size > 512) { + goto err; + } + memset(hash, 0, sizeof(blake2b_state)); + + size = size / 8; + + if (blake2b_init_key(hash, size, key, key_len) < 0) { + goto err; + } + return 0; + +err: + return -1; +} + +static void hash_update(blake2b_state* hash, uint8_t* data, size_t len) { + blake2b_update(hash, data, len); +} + +static void hash_finalize(blake2b_state* hash, uint8_t* out) { + blake2b_final(hash, out, 32); +} + +bool hash_personal_message(uint8_t* message_bytes, size_t message_byte_len, uint8_t* out_hash) { + blake2b_state inner_hash_writer; + int err = hash_init(&inner_hash_writer, 256, (uint8_t*) MESSAGE_SIGNING_KEY, 26); + if (err < 0) { + return false; + } + + hash_update(&inner_hash_writer, message_bytes, message_byte_len); + hash_finalize(&inner_hash_writer, out_hash); + + return true; +} diff --git a/src/personal_message.h b/src/personal_message.h new file mode 100644 index 0000000..d6be0dc --- /dev/null +++ b/src/personal_message.h @@ -0,0 +1,27 @@ +/***************************************************************************** + * MIT License + * + * Copyright (c) 2023 coderofstuff + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ +#include +#include + +bool hash_personal_message(uint8_t* message_bytes, size_t message_byte_len, uint8_t* out_hash); \ No newline at end of file diff --git a/src/types.h b/src/types.h index 6b42725..7d78fdc 100644 --- a/src/types.h +++ b/src/types.h @@ -40,7 +40,8 @@ typedef enum { GET_VERSION = 0x03, /// version of the application GET_APP_NAME = 0x04, /// name of the application GET_PUBLIC_KEY = 0x05, /// public key of corresponding BIP32 path - SIGN_TX = 0x06 /// sign transaction with BIP32 path + SIGN_TX = 0x06, /// sign transaction with BIP32 path + SIGN_MESSAGE = 0x07 /// sign a personal message with BIP32 path } command_e; /** @@ -75,7 +76,8 @@ typedef enum { */ typedef enum { CONFIRM_ADDRESS, /// confirm address derived from public key - CONFIRM_TRANSACTION /// confirm transaction information + CONFIRM_TRANSACTION, /// confirm transaction information + CONFIRM_MESSAGE /// confirm message information } request_type_e; /** @@ -98,14 +100,27 @@ typedef struct { uint8_t parsing_output_index; } transaction_ctx_t; +/** + * Structure for message signing information context. + */ +typedef struct { + size_t message_len; /// message length + uint8_t message[128]; /// message bytes + uint8_t message_hash[32]; /// message hash + uint8_t signature[MAX_DER_SIG_LEN]; /// signature of the message + uint8_t address_type; /// address type to use for bip32 path + uint32_t address_index; /// address index to use for bip32 path +} message_sign_ctx_t; + /** * Structure for global context. */ typedef struct { state_e state; /// state of the context union { - pubkey_ctx_t pk_info; /// public key context - transaction_ctx_t tx_info; /// transaction context + pubkey_ctx_t pk_info; /// public key context + transaction_ctx_t tx_info; /// transaction context + message_sign_ctx_t msg_info; /// message sign context }; request_type_e req_type; /// user request uint32_t bip32_path[MAX_BIP32_PATH]; /// BIP32 path diff --git a/src/ui/action/validate.c b/src/ui/action/validate.c index 393fcb2..1c7ec9c 100644 --- a/src/ui/action/validate.c +++ b/src/ui/action/validate.c @@ -42,7 +42,7 @@ void validate_transaction(bool choice) { if (choice) { G_context.state = STATE_APPROVED; - int error = crypto_sign_message(); + int error = crypto_sign_transaction(); if (error != 0) { G_context.state = STATE_NONE; io_send_sw(error); @@ -55,3 +55,20 @@ void validate_transaction(bool choice) { io_send_sw(SW_DENY); } } + +void validate_message(bool choice) { + if (choice) { + G_context.state = STATE_APPROVED; + + int error = crypto_sign_personal_message(); + if (error != 0) { + G_context.state = STATE_NONE; + io_send_sw(error); + } else { + helper_send_response_personal_message_sig(); + } + } else { + G_context.state = STATE_NONE; + io_send_sw(SW_DENY); + } +} \ No newline at end of file diff --git a/src/ui/action/validate.h b/src/ui/action/validate.h index 5499613..347fe88 100644 --- a/src/ui/action/validate.h +++ b/src/ui/action/validate.h @@ -42,3 +42,12 @@ void validate_pubkey(bool choice); * */ void validate_transaction(bool choice); + +/** + * Action for message information validation. + * + * @param[in] choice + * User choice (either approved or rejectd). + * + */ +void validate_message(bool choice); diff --git a/src/ui/bagl_display.c b/src/ui/bagl_display.c index d0ef16d..810d37d 100644 --- a/src/ui/bagl_display.c +++ b/src/ui/bagl_display.c @@ -52,6 +52,7 @@ static char g_amount[30]; static char g_bip32_path[60]; static char g_address[ECDSA_ADDRESS_LEN + 6]; static char g_fees[30]; +static char g_message[MAX_MESSAGE_LEN + 6]; // Validate/Invalidate public key and go back to home static void ui_action_validate_pubkey(bool choice) { @@ -65,6 +66,12 @@ static void ui_action_validate_transaction(bool choice) { ui_menu_main(); } +// Validate/Invalidate message and go back to home +static void ui_action_validate_message(bool choice) { + validate_message(choice); + ui_menu_main(); +} + // Step with icon and text UX_STEP_NOCB(ux_display_confirm_addr_step, pn, {&C_icon_eye, "Confirm Address"}); // Step with title/text for BIP32 path @@ -221,4 +228,51 @@ int ui_display_transaction() { return 0; } +// Step with icon and text +UX_STEP_NOCB(ux_display_confirm_message_step, pn, {&C_icon_eye, "Confirm Message"}); + +// Step with title/text for message +UX_STEP_NOCB(ux_display_message_step, + bnnn_paging, + { + .title = "Message", + .text = g_message, + }); + +// FLOW to display address and BIP32 path: +// #1 screen: eye icon + "Confirm Address" +// #2 screen: display BIP32 Path +// #3 screen: display address +// #4 screen: approve button +// #5 screen: reject button +UX_FLOW(ux_display_message_flow, + &ux_display_confirm_message_step, + &ux_display_path_step, + &ux_display_message_step, + &ux_display_approve_step, + &ux_display_reject_step); + +int ui_display_message() { + if (G_context.req_type != CONFIRM_MESSAGE || G_context.state != STATE_NONE) { + G_context.state = STATE_NONE; + return io_send_sw(SW_BAD_STATE); + } + + memset(g_bip32_path, 0, sizeof(g_bip32_path)); + if (!bip32_path_format(G_context.bip32_path, + G_context.bip32_path_len, + g_bip32_path, + sizeof(g_bip32_path))) { + return io_send_sw(SW_DISPLAY_BIP32_PATH_FAIL); + } + + memset(g_message, 0, sizeof(g_message)); + snprintf(g_message, sizeof(g_message), "%.*s", G_context.msg_info.message_len, G_context.msg_info.message); + + g_validate_callback = &ui_action_validate_message; + + ux_flow_init(0, ux_display_message_flow, NULL); + return 0; +} + #endif diff --git a/src/ui/display.h b/src/ui/display.h index 61afa84..b6c38b5 100644 --- a/src/ui/display.h +++ b/src/ui/display.h @@ -45,3 +45,11 @@ int ui_display_address(void); * */ int ui_display_transaction(void); + +/** + * Display message information on the device and ask confirmation to sign. + * + * @return 0 if success, negative integer otherwise. + * + */ +int ui_display_message(void); diff --git a/unit-tests/CMakeLists.txt b/unit-tests/CMakeLists.txt index 9299687..8a3bc36 100644 --- a/unit-tests/CMakeLists.txt +++ b/unit-tests/CMakeLists.txt @@ -47,6 +47,7 @@ include_directories(/opt/ledger-secure-sdk/lib_standard_app/) add_executable(test_address test_address.c) add_executable(test_format test_format.c) add_executable(test_sighash test_sighash.c) +add_executable(test_personal_message.h test_personal_message.c) add_executable(test_apdu_parser test_apdu_parser.c) add_executable(test_tx_parser test_tx_parser.c) add_executable(test_tx_utils test_tx_utils.c) @@ -58,6 +59,7 @@ add_library(bip32 SHARED /opt/ledger-secure-sdk/lib_standard_app/bip32.c) add_library(buffer SHARED /opt/ledger-secure-sdk/lib_standard_app/buffer.c) add_library(read SHARED /opt/ledger-secure-sdk/lib_standard_app/read.c) add_library(sighash SHARED ../src/sighash.c) +add_library(personal_message SHARED ../src/personal_message.c) add_library(write SHARED /opt/ledger-secure-sdk/lib_standard_app/write.c) add_library(format SHARED ../src/common/format.c) add_library(apdu_parser SHARED ../src/apdu/parser.c) @@ -69,6 +71,7 @@ add_library(varint SHARED /opt/ledger-secure-sdk/lib_standard_app/varint.c) target_link_libraries(test_address PUBLIC cmocka gcov address cashaddr) target_link_libraries(test_format PUBLIC cmocka gcov format) target_link_libraries(test_sighash PUBLIC cmocka gcov sighash blake2b write) +target_link_libraries(test_personal_message PUBLIC cmocka gcov personal_message blake2b write) target_link_libraries(test_apdu_parser PUBLIC cmocka gcov apdu_parser) target_link_libraries(test_tx_parser PUBLIC transaction_deserialize @@ -91,6 +94,7 @@ target_link_libraries(test_tx_utils PUBLIC add_test(test_address test_address) add_test(test_format test_format) add_test(test_sighash test_sighash) +add_test(test_personal_message test_personal_message) add_test(test_apdu_parser test_apdu_parser) add_test(test_tx_parser test_tx_parser) add_test(test_tx_utils test_tx_utils) diff --git a/unit-tests/test_personal_message.c b/unit-tests/test_personal_message.c new file mode 100644 index 0000000..7616863 --- /dev/null +++ b/unit-tests/test_personal_message.c @@ -0,0 +1,107 @@ +/***************************************************************************** + * MIT License + * + * Copyright (c) 2023 coderofstuff + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ +#include +#include +#include +#include +#include + +#include + +#include "./import/blake2-impl.h" +#include "./import/blake2b.h" +#include "personal_message.h" + +/* Start hacks */ +void os_longjmp(unsigned int exception) {} + +struct cx_xblake_s { + cx_blake2b_t blake2b; + uint64_t m[16]; + uint64_t v[16]; + uint8_t buffer[BLAKE2B_OUTBYTES]; + uint8_t block1[BLAKE2B_BLOCKBYTES]; +} ; +typedef struct cx_xblake_s cx_xblake_t; + +union cx_u { + cx_xblake_t blake; +}; +union cx_u G_cx; + +uint8_t* input_public_key; + +/* End hacks */ + +static void test_hash_personal_message_vector0(void **state) { + char message[] = "Hello Kaspa!"; // 12 chars + + uint8_t out_hash[32] = {0}; + + bool result = hash_personal_message((uint8_t*) message, 12, out_hash); + + assert_true(result); + + uint8_t res[32] = {0x2E, 0x55, 0xDE, 0xDA, 0x4A, 0x52, 0x24, 0x20, + 0x8D, 0xBD, 0x4D, 0x93, 0xCF, 0xE5, 0xAA, 0x22, + 0xD9, 0x45, 0xEA, 0xA6, 0x31, 0x72, 0xE3, 0x29, + 0xC4, 0x9A, 0xFE, 0xD6, 0x2F, 0x0E, 0x15, 0x10}; + + assert_memory_equal(out_hash, res, 32); +} + +// static void test_sign_message_vector1(void **state) { +// uint8_t private_key_data[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}; + +// char message[] = "Hello Kaspa!"; // 12 chars + +// uint8_t out_hash[64] = {0}; + +// bool result = hash_personal_message(private_key_data, (uint8_t*) message, 12, out_hash); + +// assert_true(result); + +// uint8_t res[64] = {0x40, 0xB9, 0xBB, 0x2B, 0xE0, 0xAE, 0x02, 0x60, +// 0x72, 0x79, 0xED, 0xA6, 0x40, 0x15, 0xA8, 0xD8, +// 0x6E, 0x37, 0x63, 0x27, 0x91, 0x70, 0x34, 0x0B, +// 0x82, 0x43, 0xF7, 0xCE, 0x53, 0x44, 0xD7, 0x7A, +// 0xFF, 0x11, 0x91, 0x59, 0x8B, 0xAF, 0x2F, 0xD2, +// 0x61, 0x49, 0xCA, 0xC3, 0xB4, 0xB1, 0x2C, 0x2C, +// 0x43, 0x32, 0x61, 0xC0, 0x08, 0x34, 0xDB, 0x60, +// 0x98, 0xCB, 0x17, 0x2A, 0xA4, 0x8E, 0xF5, 0x22}; + +// assert_memory_equal(out_hash, res, 64); +// } + +//612d56e633ee5da1caa4563c6ace0c98d3549ad4e3d2b1f1ea6810e6c34047bd + + +int main() { + const struct CMUnitTest tests[] = {cmocka_unit_test(test_hash_personal_message_vector0)}; + + return cmocka_run_group_tests(tests, NULL, NULL); +} From 2db1ee0d3229158ab1154325153e78972d12fa6d Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Thu, 14 Sep 2023 22:37:30 -0600 Subject: [PATCH 2/9] Add message too long handling --- doc/COMMANDS.md | 1 + src/constants.h | 7 +------ src/handler/sign_msg.c | 4 ++++ src/sw.h | 1 + 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/COMMANDS.md b/doc/COMMANDS.md index e9368c9..f15e093 100644 --- a/doc/COMMANDS.md +++ b/doc/COMMANDS.md @@ -173,4 +173,5 @@ Transactions signed with ECDSA are currently not supported. | 0xB00A | `SW_WRONG_BIP32_COIN_TYPE` | `Coin Type` must be `111111'` | | 0xB00B | `SW_WRONG_BIP32_TYPE` | `Type` passed is not valid. Must be either `0` for `Receive` or `1` for `Change`| | 0xB00C | `SW_WRONG_BIP32_PATH_LEN` | Path length must be `5` | +| 0xB00D | `SW_MESSAGE_TOO_LONG` | Message len greater than max | | 0x9000 | `OK` | Success | diff --git a/src/constants.h b/src/constants.h index 9f28ff4..9c4e022 100644 --- a/src/constants.h +++ b/src/constants.h @@ -43,15 +43,10 @@ */ #define MAX_APPNAME_LEN 64 -/** - * Maximum transaction length (bytes). - */ -#define MAX_TRANSACTION_LEN 128 - /** * Maximum message length (bytes) */ -#define MAX_MESSAGE_LEN 128 +#define MAX_MESSAGE_LEN 200 /** * Maximum signature length (bytes). diff --git a/src/handler/sign_msg.c b/src/handler/sign_msg.c index cc4a51e..bc1c7ec 100644 --- a/src/handler/sign_msg.c +++ b/src/handler/sign_msg.c @@ -62,6 +62,10 @@ int handler_sign_msg(buffer_t *cdata) { return io_send_sw(SW_WRONG_DATA_LENGTH); } + if (message_len > MAX_MESSAGE_LEN) { + return io_send_sw(SW_MESSAGE_TOO_LONG); + } + G_context.msg_info.message_len = (size_t) message_len; if (!buffer_can_read(cdata, G_context.msg_info.message_len)) { diff --git a/src/sw.h b/src/sw.h index 97fb3ce..2f81e8a 100644 --- a/src/sw.h +++ b/src/sw.h @@ -88,3 +88,4 @@ #define SW_WRONG_BIP32_COIN_TYPE 0xB00A #define SW_WRONG_BIP32_TYPE 0xB00B #define SW_WRONG_BIP32_PATH_LEN 0xB00C +#define SW_MESSAGE_TOO_LONG 0xB00D From ff8b6c5b7c7177f220bbc8e52b6e4cef0cc97d9a Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Thu, 14 Sep 2023 23:00:30 -0600 Subject: [PATCH 3/9] Working unit tests for Nano S/SP/X --- .../kaspa_command_sender.py | 15 ++- tests/application_client/kaspa_message.py | 30 +++++ .../kaspa_response_unpacker.py | 18 +++ .../nanos/test_sign_message_kanji/00000.png | Bin 0 -> 371 bytes .../nanos/test_sign_message_kanji/00001.png | Bin 0 -> 335 bytes .../nanos/test_sign_message_kanji/00002.png | Bin 0 -> 334 bytes .../nanos/test_sign_message_kanji/00003.png | Bin 0 -> 341 bytes .../nanos/test_sign_message_kanji/00004.png | Bin 0 -> 411 bytes .../nanos/test_sign_message_simple/00000.png | Bin 0 -> 371 bytes .../nanos/test_sign_message_simple/00001.png | Bin 0 -> 334 bytes .../nanos/test_sign_message_simple/00002.png | Bin 0 -> 387 bytes .../nanos/test_sign_message_simple/00003.png | Bin 0 -> 341 bytes .../nanos/test_sign_message_simple/00004.png | Bin 0 -> 411 bytes .../nanosp/test_sign_message_kanji/00000.png | Bin 0 -> 399 bytes .../nanosp/test_sign_message_kanji/00001.png | Bin 0 -> 368 bytes .../nanosp/test_sign_message_kanji/00002.png | Bin 0 -> 310 bytes .../nanosp/test_sign_message_kanji/00003.png | Bin 0 -> 364 bytes .../nanosp/test_sign_message_kanji/00004.png | Bin 0 -> 474 bytes .../nanosp/test_sign_message_simple/00000.png | Bin 0 -> 399 bytes .../nanosp/test_sign_message_simple/00001.png | Bin 0 -> 375 bytes .../nanosp/test_sign_message_simple/00002.png | Bin 0 -> 461 bytes .../nanosp/test_sign_message_simple/00003.png | Bin 0 -> 364 bytes .../nanosp/test_sign_message_simple/00004.png | Bin 0 -> 474 bytes .../nanox/test_sign_message_kanji/00000.png | Bin 0 -> 399 bytes .../nanox/test_sign_message_kanji/00001.png | Bin 0 -> 368 bytes .../nanox/test_sign_message_kanji/00002.png | Bin 0 -> 310 bytes .../nanox/test_sign_message_kanji/00003.png | Bin 0 -> 364 bytes .../nanox/test_sign_message_kanji/00004.png | Bin 0 -> 474 bytes .../nanox/test_sign_message_simple/00000.png | Bin 0 -> 399 bytes .../nanox/test_sign_message_simple/00001.png | Bin 0 -> 375 bytes .../nanox/test_sign_message_simple/00002.png | Bin 0 -> 461 bytes .../nanox/test_sign_message_simple/00003.png | Bin 0 -> 364 bytes .../nanox/test_sign_message_simple/00004.png | Bin 0 -> 474 bytes tests/test_sign_cmd.py | 18 +-- tests/test_sign_personal_message_cmd.py | 111 ++++++++++++++++++ tests/utils.py | 4 +- 36 files changed, 181 insertions(+), 15 deletions(-) create mode 100644 tests/application_client/kaspa_message.py create mode 100644 tests/snapshots/nanos/test_sign_message_kanji/00000.png create mode 100644 tests/snapshots/nanos/test_sign_message_kanji/00001.png create mode 100644 tests/snapshots/nanos/test_sign_message_kanji/00002.png create mode 100644 tests/snapshots/nanos/test_sign_message_kanji/00003.png create mode 100644 tests/snapshots/nanos/test_sign_message_kanji/00004.png create mode 100644 tests/snapshots/nanos/test_sign_message_simple/00000.png create mode 100644 tests/snapshots/nanos/test_sign_message_simple/00001.png create mode 100644 tests/snapshots/nanos/test_sign_message_simple/00002.png create mode 100644 tests/snapshots/nanos/test_sign_message_simple/00003.png create mode 100644 tests/snapshots/nanos/test_sign_message_simple/00004.png create mode 100644 tests/snapshots/nanosp/test_sign_message_kanji/00000.png create mode 100644 tests/snapshots/nanosp/test_sign_message_kanji/00001.png create mode 100644 tests/snapshots/nanosp/test_sign_message_kanji/00002.png create mode 100644 tests/snapshots/nanosp/test_sign_message_kanji/00003.png create mode 100644 tests/snapshots/nanosp/test_sign_message_kanji/00004.png create mode 100644 tests/snapshots/nanosp/test_sign_message_simple/00000.png create mode 100644 tests/snapshots/nanosp/test_sign_message_simple/00001.png create mode 100644 tests/snapshots/nanosp/test_sign_message_simple/00002.png create mode 100644 tests/snapshots/nanosp/test_sign_message_simple/00003.png create mode 100644 tests/snapshots/nanosp/test_sign_message_simple/00004.png create mode 100644 tests/snapshots/nanox/test_sign_message_kanji/00000.png create mode 100644 tests/snapshots/nanox/test_sign_message_kanji/00001.png create mode 100644 tests/snapshots/nanox/test_sign_message_kanji/00002.png create mode 100644 tests/snapshots/nanox/test_sign_message_kanji/00003.png create mode 100644 tests/snapshots/nanox/test_sign_message_kanji/00004.png create mode 100644 tests/snapshots/nanox/test_sign_message_simple/00000.png create mode 100644 tests/snapshots/nanox/test_sign_message_simple/00001.png create mode 100644 tests/snapshots/nanox/test_sign_message_simple/00002.png create mode 100644 tests/snapshots/nanox/test_sign_message_simple/00003.png create mode 100644 tests/snapshots/nanox/test_sign_message_simple/00004.png create mode 100644 tests/test_sign_personal_message_cmd.py diff --git a/tests/application_client/kaspa_command_sender.py b/tests/application_client/kaspa_command_sender.py index de9f77d..23502aa 100644 --- a/tests/application_client/kaspa_command_sender.py +++ b/tests/application_client/kaspa_command_sender.py @@ -6,6 +6,7 @@ from ragger.bip import pack_derivation_path from .kaspa_transaction import Transaction +from .kaspa_message import PersonalMessage MAX_APDU_LEN: int = 255 @@ -34,6 +35,7 @@ class InsType(IntEnum): GET_APP_NAME = 0x04 GET_PUBLIC_KEY = 0x05 SIGN_TX = 0x06 + SIGN_MESSAGE = 0x07 class Errors(IntEnum): SW_DENY = 0x6985 @@ -54,13 +56,11 @@ class Errors(IntEnum): SW_WRONG_BIP32_COIN_TYPE = 0xB00A SW_WRONG_BIP32_TYPE = 0xB00B SW_WRONG_BIP32_PATH_LEN = 0xB00C - - + SW_MESSAGE_TOO_LONG = 0xB00D def split_message(message: bytes, max_size: int) -> List[bytes]: return [message[x:x + max_size] for x in range(0, len(message), max_size)] - class KaspaCommandSender: def __init__(self, backend: BackendInterface) -> None: self.backend = backend @@ -140,6 +140,15 @@ def sign_tx(self, transaction: Transaction) -> Generator[None, None, None]: data=txinput.serialize()) as response: yield response + + @contextmanager + def sign_message(self, message_data: PersonalMessage) -> Generator[None, None, None]: + with self.backend.exchange_async(cla=CLA, + ins=InsType.SIGN_MESSAGE, + p1=P1.P1_CONFIRM, + p2=P2.P2_LAST, + data=message_data.serialize()) as response: + yield response def get_next_signature(self) -> RAPDU: return self.backend.exchange(cla=CLA, diff --git a/tests/application_client/kaspa_message.py b/tests/application_client/kaspa_message.py new file mode 100644 index 0000000..bab4a6f --- /dev/null +++ b/tests/application_client/kaspa_message.py @@ -0,0 +1,30 @@ +from io import BytesIO +from typing import Union +from hashlib import blake2b + +from .kaspa_utils import read, read_uint + +def hash_init() -> blake2b: + return blake2b(digest_size=32, key=bytes("PersonalMessageSigningHash", "ascii")) + +class PersonalMessage: + def __init__(self, + address_type: int, + address_index: int, + message: str): + self.address_type: int = address_type # 1 byte + self.address_index:int = address_index # 4 bytes + self.message: bytes = bytes(message, 'utf8') # var + + def serialize(self) -> bytes: + return b"".join([ + self.address_type.to_bytes(1, byteorder="big"), + self.address_index.to_bytes(4, byteorder="big"), + len(self.message).to_bytes(1, byteorder="big"), + self.message + ]) + + def to_hash(self) -> bytes: + outer_hash = hash_init() + outer_hash.update(self.message) + return outer_hash.digest() \ No newline at end of file diff --git a/tests/application_client/kaspa_response_unpacker.py b/tests/application_client/kaspa_response_unpacker.py index 9f586ef..ed3a1af 100644 --- a/tests/application_client/kaspa_response_unpacker.py +++ b/tests/application_client/kaspa_response_unpacker.py @@ -62,6 +62,8 @@ def unpack_get_public_key_response(response: bytes) -> Tuple[int, bytes, int, by # input_index (1) # der_sig_len (1) # der_sig (64) +# sighash_len (1) +# sighash (32) def unpack_sign_tx_response(response: bytes) -> Tuple[int, int, int, bytes, int, bytes]: response, has_more = pop_sized_buf_from_buffer(response, 1) response, input_index = pop_sized_buf_from_buffer(response, 1) @@ -76,3 +78,19 @@ def unpack_sign_tx_response(response: bytes) -> Tuple[int, int, int, bytes, int, der_sig, \ sighash_len, \ sighash + +# Unpack from response: +# response = der_sig_len (1) +# der_sig (64) +# hash_len (1) +# hash (32) +def unpack_sign_message_response(response: bytes) -> Tuple[int, int, int, bytes, int, bytes]: + response, der_sig_len, der_sig = pop_size_prefixed_buf_from_buf(response) + response, hash_len, hash = pop_size_prefixed_buf_from_buf(response) + + assert len(response) == 0 + + return der_sig_len, \ + der_sig, \ + hash_len, \ + hash \ No newline at end of file diff --git a/tests/snapshots/nanos/test_sign_message_kanji/00000.png b/tests/snapshots/nanos/test_sign_message_kanji/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..f81b25d230f8bdcdac05615cccd494571788979c GIT binary patch literal 371 zcmV-(0gV2MP)4&GVGQDr2@!~bAP9ngW$~WCRkrnWy}bP9VFl0u zx%4@hZa{Ouu6{1J+6ltLdjgkWLIdiK$+mvwpL!Dn%m@hFD1GLbpFg2S0Mi;%`UF}P zMBruUwz7EwIv|1jBPM(h+zxWioQ3d#C!xM4p}r@f{%DxXP-8im%#)#|KFh}`^$f|= zWNmy&rugt;^}yx;DySwm=w+a!9yJ1Tb7pvX>z^5(Y^psaD+fyZV)FX1^YG@1A$_~E z)I9TOb=an%8Zk!z3aZc8nxV#P)0pkd<$yg$$(*1bqV1x~DnMo)Ir1+uk9j*9y0ERR zG3w17a=k4A(u~2yKy;Qwd R6kGrR002ovPDHLkV1le)r|kd$ literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_message_kanji/00001.png b/tests/snapshots/nanos/test_sign_message_kanji/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..17e44240c29800af269cb74eed4f796fb7fc7151 GIT binary patch literal 335 zcmV-V0kHmwP) z0P=C0+I+md4QPUtMSP6EG53=KO2Nu~YA1=LHhnd$PyuB+Pw!SeD+GXTBc#_TV=y`64rbFUojuQ zhu;PH#zyn@dmS hA3gy900015`2g4r=w9R~IVb=C002ovPDHLkV1oZljwJv9 literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_message_kanji/00002.png b/tests/snapshots/nanos/test_sign_message_kanji/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..82a806e97531d870a035ed64ff56a26dd0b48cfd GIT binary patch literal 334 zcmV-U0kQsxP)S|Nn#gusw8XNK2I_&U-iRd08c`FhD^|5kd$dV7%7yT04^e<$*RJJ5RI$ z0ru5Umm5P@a`jbeHec)>afj}MJ3PzdQz7`N6<{ScbL}wbQv%o1VDmAaq*v>}eK=Hg zdH)6tXSp$mgper!_45lXN}K9NZ5&vH&pVZsP!#0(+2MBmqs$0a?138FoU{;}1M0$& zdQ+&&b)-qopTo`Ai*S3|ng6||iy;ODv=buK5o|#TX%+mmD*yyR8*0IJ!+ClEA%qYq zLA5uLvlx_wxG+Yry2qARt#sf<#$}=)VJ~ zBlvESR-Jq3=$jydfC?r!$iuAw9oGJ!U-M%YMJ+y&Ch%TCM^JUq5BGkf8O_{y`#mQ} nq4{V^xv44i3V1v$0C_ea3_go|-rj`700000NkvXXu0mjfd&QW1 literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_message_kanji/00004.png b/tests/snapshots/nanos/test_sign_message_kanji/00004.png new file mode 100644 index 0000000000000000000000000000000000000000..9ab62488898414fa0b4d01c83ce19cd254158238 GIT binary patch literal 411 zcmV;M0c8G(P)gPVv!e{1wVPd@+= z5p63?%kDA~#^XqG8AnQkpux7*a=%m`b>nhXOa>}oT51)*2kUw5D(;a!0ZQ+D)&Zmj zCFiNnEDg#$v+};Cb)1bt(4hY}-ni6)IunrBLCN&xlH2qyXB>Hlkl@KmC@;r_!*8I) zlh5hbx(yt*eFqUP$^=kEA6st)dkua9sB`}jH}Ebt(_ofEU^pz@nFZ-I@ScqKvp1Xl zB79bZ{w?6pvNKrI!s^9A?BOE;G%yW|p1lxDH2iZKfUf5^~(CIA4yGhfVf$DpW>Y_k9W002ovPDHLk FV1k#gxOo5o literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_message_simple/00000.png b/tests/snapshots/nanos/test_sign_message_simple/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..f81b25d230f8bdcdac05615cccd494571788979c GIT binary patch literal 371 zcmV-(0gV2MP)4&GVGQDr2@!~bAP9ngW$~WCRkrnWy}bP9VFl0u zx%4@hZa{Ouu6{1J+6ltLdjgkWLIdiK$+mvwpL!Dn%m@hFD1GLbpFg2S0Mi;%`UF}P zMBruUwz7EwIv|1jBPM(h+zxWioQ3d#C!xM4p}r@f{%DxXP-8im%#)#|KFh}`^$f|= zWNmy&rugt;^}yx;DySwm=w+a!9yJ1Tb7pvX>z^5(Y^psaD+fyZV)FX1^YG@1A$_~E z)I9TOb=an%8Zk!z3aZc8nxV#P)0pkd<$yg$$(*1bqV1x~DnMo)Ir1+uk9j*9y0ERR zG3w17a=k4A(u~2yKy;Qwd R6kGrR002ovPDHLkV1le)r|kd$ literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_message_simple/00001.png b/tests/snapshots/nanos/test_sign_message_simple/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..ef269c94f41fd8cdd7e60a8ce7b0b697ce790204 GIT binary patch literal 334 zcmV-U0kQsxP)9si5ULw9^QuwtO~t$bdSWmp7{%4-O#9NKtCs^0MB* z)A5i2B;0x6{?zrK)JxMaFRVWS*2u8_Gze3}`jdeVEI}2rWXL(pt!j1%j=fwvXhiaK z;SSSmoFWxChJ-k`1Mc+-q1G8U(kIleEd&MXFJZ3vUXRymwj(utt90nTgyq)%SJZv) z>8%J`-$RKRq!LI3~&07*qoM6N<$f?O??!vFvP literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_message_simple/00002.png b/tests/snapshots/nanos/test_sign_message_simple/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..0964ed838b8e071e0db87776366f34dd99b4e945 GIT binary patch literal 387 zcmV-}0et?6P)Nklos`7y+eOmEYt$C1XY)pln+Z1VIqEah==z6^xU<%Kxu0 zN*Ft)ny^2k93X~sGF&++Q5$j7aG}Mfe9foryhe<2fVM;b|J%E-psi1Z<$djR0P#*i zO@f{KK+8Pk&sD>*1JiaxGs@ji`QS2Vb7(3%P5Slhu46-8bKo hf~F-L5ClQ6E_wxG+Yry2qARt#sf<#$}=)VJ~ zBlvESR-Jq3=$jydfC?r!$iuAw9oGJ!U-M%YMJ+y&Ch%TCM^JUq5BGkf8O_{y`#mQ} nq4{V^xv44i3V1v$0C_ea3_go|-rj`700000NkvXXu0mjfd&QW1 literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_message_simple/00004.png b/tests/snapshots/nanos/test_sign_message_simple/00004.png new file mode 100644 index 0000000000000000000000000000000000000000..9ab62488898414fa0b4d01c83ce19cd254158238 GIT binary patch literal 411 zcmV;M0c8G(P)gPVv!e{1wVPd@+= z5p63?%kDA~#^XqG8AnQkpux7*a=%m`b>nhXOa>}oT51)*2kUw5D(;a!0ZQ+D)&Zmj zCFiNnEDg#$v+};Cb)1bt(4hY}-ni6)IunrBLCN&xlH2qyXB>Hlkl@KmC@;r_!*8I) zlh5hbx(yt*eFqUP$^=kEA6st)dkua9sB`}jH}Ebt(_ofEU^pz@nFZ-I@ScqKvp1Xl zB79bZ{w?6pvNKrI!s^9A?BOE;G%yW|p1lxDH2iZKfUf5^~(CIA4yGhfVf$DpW>Y_k9W002ovPDHLk FV1k#gxOo5o literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanosp/test_sign_message_kanji/00000.png b/tests/snapshots/nanosp/test_sign_message_kanji/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..a95fdd26f372c9b936555276daf0234a6d63a0dc GIT binary patch literal 399 zcmV;A0dW3_P)uO23*$P?WUkY3nc%rVW2M~wBM9*|mG%teu@a*(=7*QeH>W^Ccd+}6Lerk7(d54nHNB8%C*9zb6H~+F#&LP%Y z&ebI}TipIN;~g>eUn_h&R&>fg^4}+Fwu4!uzR2^KvrUbOrHWKo0(d6&aZX4`#q8aXoam8e|@3N?zwgreqCE)_7=7zuAeh!?Ii`T zc>mlb$Io(ANquaxEr~q!Up0%Y9+KbAqh&l6v+|wEhvdw_*41$h{2{ zg1QXn-QK^WG*15bqpcH@K74vO^P4TByNThkv>?}rpB^sS6;+Fh~K z-qAeerT^uQs9%#;9`xFE!ON~aTu2|N1PW@-=%0~Y%c#3+-6W8Rr>mdKI;Vst0Eozj A9smFU literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanosp/test_sign_message_kanji/00003.png b/tests/snapshots/nanosp/test_sign_message_kanji/00003.png new file mode 100644 index 0000000000000000000000000000000000000000..53ae65195fbea5b281a1bc1a80351dbf1cd79ff8 GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!2~2@x4h6`U|=-%ba4!+nDh2#AYZeBfa}G~ z%X2sUSKTFSd4J{-YHcY(QO5;J{<~e9q=7F?O4)!WO}6UUdH! zS+Hz=(4})vCM2-VD4nt3W%LdvkyzeG%km#`1t_mu*zR}#jNB{EKZnW}g5-=Bym-_% z`=7%C>zxJL|9msNSMXnbQRayy^)nr>EU7olTHqoc^vG(B%bo(Id*|kR{84!`z2x6n zZ`;PkbrPvd6U}A>Y0chs_tyHmLi6kw6c{>JvYiQ=+MTFTx8d*9^V|R0+_75oZt9or zLetinU!`YMvFyLCb8XxElhO0{v2rTkNR$jMW7~4}*8a52+MC^J%KMbxPN-JRb2RNP zEsp0ebAPS3=e2G53#Z$XZAI6Yd=Y%U^7k#000000058qS{=Y2rIfm# z#~2@u0o)_TXq5DtSpmxQkH6}x<U=PLxu-Mr%5Ugaaf2e?C2Z43Hv^6K`e1sm5f z#!kYe=2}W=63=LT%r`Eb0d`hE7?ow6HlA(fTpmGpv zk6MRAjegFUf008iW9~!6^t%;Me Q&Hw-a07*qoM6N<$g7a(EssI20 literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanosp/test_sign_message_simple/00000.png b/tests/snapshots/nanosp/test_sign_message_simple/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..a95fdd26f372c9b936555276daf0234a6d63a0dc GIT binary patch literal 399 zcmV;A0dW3_P)uO23*$P?WUkY3nc%rVW2M~wBM9*|mG%teu@a*(=7*QeH>W^Ccd+}6Cld?oMg^w`sP-12pwC>QSk?e60;D?4u6-LlWQ8=v*~TaD^jSA-^6>reV#!|$k`ka=R?s((-BT;(>s z{rrctS{{SC;DVT(3%o`b?=KU~TC`u%@`H=$rxKx*q75PsS%J<&2Gf2rZ@OdsQ{8gX PA&{`AtDnm{r-UW|Wpbv? literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanosp/test_sign_message_simple/00002.png b/tests/snapshots/nanosp/test_sign_message_simple/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..6df9c9df488d0cf8e3ff56ebe9be01413918d2a2 GIT binary patch literal 461 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!2~2@x4h6`U|^i$>EaktG3V{Az`Vl>JPnCq zZ`JPn_qel^e}$k?f`?Sjl|T1`-6aK__c(}wbS1nyzxwf%pnn3%Z>HKDJYCJ;|NXsf z!-SwNL%GxOHKjG@wjbRp6lk#~C-c6wLc7|r8$DAv!Xkz2okYKH>but}`QLiM%Z}Ef z^eM#w(|nEvzCYCSnPtk!FfSoydkEUAyNKu>ZJM-rQo?T z&xB?#Tks+B&8bCUUR9BBSUuQpVc;vbMDUV zN}uh$cy?CJT=`0_Q@fMi2gW?yBRKme3-9ZW7uvJ8o_rj1dZ)>(hI=z_efY74C$D(s z^;ToUwYNj~)=f783UmGam-V^OY5m_#0rA)4s+0d;z7Q=X`0;J3++OSH+nMY?x$pSy z_clj1@c(W{--+c7Pan5bNEYn$i`=}kOZ`9Nf`4moI~!&c&o@4_v_^mP?cdIevD4cuHn_ckM5kA4=SnQYFSd4J{-YHcY(QO5;J{<~e9q=7F?O4)!WO}6UUdH! zS+Hz=(4})vCM2-VD4nt3W%LdvkyzeG%km#`1t_mu*zR}#jNB{EKZnW}g5-=Bym-_% z`=7%C>zxJL|9msNSMXnbQRayy^)nr>EU7olTHqoc^vG(B%bo(Id*|kR{84!`z2x6n zZ`;PkbrPvd6U}A>Y0chs_tyHmLi6kw6c{>JvYiQ=+MTFTx8d*9^V|R0+_75oZt9or zLetinU!`YMvFyLCb8XxElhO0{v2rTkNR$jMW7~4}*8a52+MC^J%KMbxPN-JRb2RNP zEsp0ebAPS3=e2G53#Z$XZAI6Yd=Y%U^7k#000000058qS{=Y2rIfm# z#~2@u0o)_TXq5DtSpmxQkH6}x<U=PLxu-Mr%5Ugaaf2e?C2Z43Hv^6K`e1sm5f z#!kYe=2}W=63=LT%r`Eb0d`hE7?ow6HlA(fTpmGpv zk6MRAjegFUf008iW9~!6^t%;Me Q&Hw-a07*qoM6N<$g7a(EssI20 literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanox/test_sign_message_kanji/00000.png b/tests/snapshots/nanox/test_sign_message_kanji/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..a95fdd26f372c9b936555276daf0234a6d63a0dc GIT binary patch literal 399 zcmV;A0dW3_P)uO23*$P?WUkY3nc%rVW2M~wBM9*|mG%teu@a*(=7*QeH>W^Ccd+}6Lerk7(d54nHNB8%C*9zb6H~+F#&LP%Y z&ebI}TipIN;~g>eUn_h&R&>fg^4}+Fwu4!uzR2^KvrUbOrHWKo0(d6&aZX4`#q8aXoam8e|@3N?zwgreqCE)_7=7zuAeh!?Ii`T zc>mlb$Io(ANquaxEr~q!Up0%Y9+KbAqh&l6v+|wEhvdw_*41$h{2{ zg1QXn-QK^WG*15bqpcH@K74vO^P4TByNThkv>?}rpB^sS6;+Fh~K z-qAeerT^uQs9%#;9`xFE!ON~aTu2|N1PW@-=%0~Y%c#3+-6W8Rr>mdKI;Vst0Eozj A9smFU literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanox/test_sign_message_kanji/00003.png b/tests/snapshots/nanox/test_sign_message_kanji/00003.png new file mode 100644 index 0000000000000000000000000000000000000000..53ae65195fbea5b281a1bc1a80351dbf1cd79ff8 GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!2~2@x4h6`U|=-%ba4!+nDh2#AYZeBfa}G~ z%X2sUSKTFSd4J{-YHcY(QO5;J{<~e9q=7F?O4)!WO}6UUdH! zS+Hz=(4})vCM2-VD4nt3W%LdvkyzeG%km#`1t_mu*zR}#jNB{EKZnW}g5-=Bym-_% z`=7%C>zxJL|9msNSMXnbQRayy^)nr>EU7olTHqoc^vG(B%bo(Id*|kR{84!`z2x6n zZ`;PkbrPvd6U}A>Y0chs_tyHmLi6kw6c{>JvYiQ=+MTFTx8d*9^V|R0+_75oZt9or zLetinU!`YMvFyLCb8XxElhO0{v2rTkNR$jMW7~4}*8a52+MC^J%KMbxPN-JRb2RNP zEsp0ebAPS3=e2G53#Z$XZAI6Yd=YK000000Kjcts{{C_lv4Nm z7~{>6oa9%4QR-_(W%yYgz%^owMoF)k6`)N2_@};FJ|0;mBFqZVGM)H^YXRyxZe0V{ z0tBmlX2Q4t&tO~t>z$`?EkK=p>%GXe0EKn-!(&duc|p{tgj-`e;k`P5Yxu4MzZH-@ zrWpqSLVWLL7IxCBll?jpov1D`9FEjDOE6MVU8Nq>yL=`10Jn*%Z9#8NUfmwGVB zbyh%@*TMPUh-lMm(2T41qS4%MZ@G_oVc^6u(e^K7+))4kz-k|TfN^{}dKBdXs2s%F zqt@ooIBI+z?1P4;2_x0`T5q>wbEGLWx}@0`%2ZZB?a17mG@`x86`*V>^BS~QyUikf zas|jfv^$r+sm|^%SAZk`@2vaJqg$>~kNUf)RfT38?lOPT4*&oF008dr3v^`?fmkS) QN&o-=07*qoM6N<$g1|W1y8r+H literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanox/test_sign_message_simple/00000.png b/tests/snapshots/nanox/test_sign_message_simple/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..a95fdd26f372c9b936555276daf0234a6d63a0dc GIT binary patch literal 399 zcmV;A0dW3_P)uO23*$P?WUkY3nc%rVW2M~wBM9*|mG%teu@a*(=7*QeH>W^Ccd+}6Cld?oMg^w`sP-12pwC>QSk?e60;D?4u6-LlWQ8=v*~TaD^jSA-^6>reV#!|$k`ka=R?s((-BT;(>s z{rrctS{{SC;DVT(3%o`b?=KU~TC`u%@`H=$rxKx*q75PsS%J<&2Gf2rZ@OdsQ{8gX PA&{`AtDnm{r-UW|Wpbv? literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanox/test_sign_message_simple/00002.png b/tests/snapshots/nanox/test_sign_message_simple/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..6df9c9df488d0cf8e3ff56ebe9be01413918d2a2 GIT binary patch literal 461 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!2~2@x4h6`U|^i$>EaktG3V{Az`Vl>JPnCq zZ`JPn_qel^e}$k?f`?Sjl|T1`-6aK__c(}wbS1nyzxwf%pnn3%Z>HKDJYCJ;|NXsf z!-SwNL%GxOHKjG@wjbRp6lk#~C-c6wLc7|r8$DAv!Xkz2okYKH>but}`QLiM%Z}Ef z^eM#w(|nEvzCYCSnPtk!FfSoydkEUAyNKu>ZJM-rQo?T z&xB?#Tks+B&8bCUUR9BBSUuQpVc;vbMDUV zN}uh$cy?CJT=`0_Q@fMi2gW?yBRKme3-9ZW7uvJ8o_rj1dZ)>(hI=z_efY74C$D(s z^;ToUwYNj~)=f783UmGam-V^OY5m_#0rA)4s+0d;z7Q=X`0;J3++OSH+nMY?x$pSy z_clj1@c(W{--+c7Pan5bNEYn$i`=}kOZ`9Nf`4moI~!&c&o@4_v_^mP?cdIevD4cuHn_ckM5kA4=SnQYFSd4J{-YHcY(QO5;J{<~e9q=7F?O4)!WO}6UUdH! zS+Hz=(4})vCM2-VD4nt3W%LdvkyzeG%km#`1t_mu*zR}#jNB{EKZnW}g5-=Bym-_% z`=7%C>zxJL|9msNSMXnbQRayy^)nr>EU7olTHqoc^vG(B%bo(Id*|kR{84!`z2x6n zZ`;PkbrPvd6U}A>Y0chs_tyHmLi6kw6c{>JvYiQ=+MTFTx8d*9^V|R0+_75oZt9or zLetinU!`YMvFyLCb8XxElhO0{v2rTkNR$jMW7~4}*8a52+MC^J%KMbxPN-JRb2RNP zEsp0ebAPS3=e2G53#Z$XZAI6Yd=YK000000Kjcts{{C_lv4Nm z7~{>6oa9%4QR-_(W%yYgz%^owMoF)k6`)N2_@};FJ|0;mBFqZVGM)H^YXRyxZe0V{ z0tBmlX2Q4t&tO~t>z$`?EkK=p>%GXe0EKn-!(&duc|p{tgj-`e;k`P5Yxu4MzZH-@ zrWpqSLVWLL7IxCBll?jpov1D`9FEjDOE6MVU8Nq>yL=`10Jn*%Z9#8NUfmwGVB zbyh%@*TMPUh-lMm(2T41qS4%MZ@G_oVc^6u(e^K7+))4kz-k|TfN^{}dKBdXs2s%F zqt@ooIBI+z?1P4;2_x0`T5q>wbEGLWx}@0`%2ZZB?a17mG@`x86`*V>^BS~QyUikf zas|jfv^$r+sm|^%SAZk`@2vaJqg$>~kNUf)RfT38?lOPT4*&oF008dr3v^`?fmkS) QN&o-=07*qoM6N<$g1|W1y8r+H literal 0 HcmV?d00001 diff --git a/tests/test_sign_cmd.py b/tests/test_sign_cmd.py index 0c7dd6d..492e3bf 100644 --- a/tests/test_sign_cmd.py +++ b/tests/test_sign_cmd.py @@ -64,7 +64,7 @@ def test_sign_tx_simple(firmware, backend, navigator, test_name): response = client.get_async_response().data _, _, _, der_sig, _, sighash = unpack_sign_tx_response(response) assert transaction.get_sighash(0) == sighash - assert check_signature_validity(public_key, der_sig, sighash, transaction) + assert check_signature_validity(public_key, der_sig, sighash) def test_sign_tx_simple_ecdsa(firmware, backend, navigator, test_name): # Use the app interface instead of raw interface @@ -120,7 +120,7 @@ def test_sign_tx_simple_ecdsa(firmware, backend, navigator, test_name): response = client.get_async_response().data _, _, _, der_sig, _, sighash = unpack_sign_tx_response(response) assert transaction.get_sighash(0) == sighash - assert check_signature_validity(public_key, der_sig, sighash, transaction) + assert check_signature_validity(public_key, der_sig, sighash) def test_sign_tx_p2sh(firmware, backend, navigator, test_name): @@ -177,7 +177,7 @@ def test_sign_tx_p2sh(firmware, backend, navigator, test_name): response = client.get_async_response().data _, _, _, der_sig, _, sighash = unpack_sign_tx_response(response) assert transaction.get_sighash(0) == sighash - assert check_signature_validity(public_key, der_sig, sighash, transaction) + assert check_signature_validity(public_key, der_sig, sighash) def test_sign_tx_simple_sendint(firmware, backend, navigator, test_name): # Use the app interface instead of raw interface @@ -233,7 +233,7 @@ def test_sign_tx_simple_sendint(firmware, backend, navigator, test_name): response = client.get_async_response().data _, _, _, der_sig, _, sighash = unpack_sign_tx_response(response) assert transaction.get_sighash(0) == sighash - assert check_signature_validity(public_key, der_sig, sighash, transaction) + assert check_signature_validity(public_key, der_sig, sighash) def test_sign_tx_simple_sendmaxu64(firmware, backend, navigator, test_name): # Use the app interface instead of raw interface @@ -289,7 +289,7 @@ def test_sign_tx_simple_sendmaxu64(firmware, backend, navigator, test_name): response = client.get_async_response().data _, _, _, der_sig, _, sighash = unpack_sign_tx_response(response) assert transaction.get_sighash(0) == sighash - assert check_signature_validity(public_key, der_sig, sighash, transaction) + assert check_signature_validity(public_key, der_sig, sighash) def test_sign_tx_simple_change_idx1(firmware, backend, navigator, test_name): # Use the app interface instead of raw interface @@ -358,7 +358,7 @@ def test_sign_tx_simple_change_idx1(firmware, backend, navigator, test_name): response = client.get_async_response().data _, _, _, der_sig, _, sighash = unpack_sign_tx_response(response) assert transaction.get_sighash(0) == sighash - assert check_signature_validity(public_key, der_sig, sighash, transaction) + assert check_signature_validity(public_key, der_sig, sighash) def test_sign_tx_with_change(firmware, backend, navigator, test_name): # Use the app interface instead of raw interface @@ -423,7 +423,7 @@ def test_sign_tx_with_change(firmware, backend, navigator, test_name): response = client.get_async_response().data _, _, _, der_sig, _, sighash = unpack_sign_tx_response(response) assert transaction.get_sighash(0) == sighash - assert check_signature_validity(public_key, der_sig, sighash, transaction) + assert check_signature_validity(public_key, der_sig, sighash) def test_sign_tx_with_invalid_change(backend): backend.raise_policy = RaisePolicy.RAISE_NOTHING @@ -666,7 +666,7 @@ def test_sign_tx_max(firmware, backend, navigator, test_name): response = client.get_async_response().data has_more, input_index, _, der_sig, _, sighash = unpack_sign_tx_response(response) assert transaction.get_sighash(input_index) == sighash - assert check_signature_validity(public_key, der_sig, sighash, transaction) + assert check_signature_validity(public_key, der_sig, sighash) while has_more > 0: idx = idx + 1 @@ -677,7 +677,7 @@ def test_sign_tx_max(firmware, backend, navigator, test_name): response = client.get_next_signature().data has_more, input_index, _, der_sig, _, sighash = unpack_sign_tx_response(response) assert transaction.get_sighash(input_index) == sighash - assert check_signature_validity(public_key, der_sig, sighash, transaction) + assert check_signature_validity(public_key, der_sig, sighash) # Transaction signature refused test # The test will ask for a transaction signature that will be refused on screen diff --git a/tests/test_sign_personal_message_cmd.py b/tests/test_sign_personal_message_cmd.py new file mode 100644 index 0000000..34b53fd --- /dev/null +++ b/tests/test_sign_personal_message_cmd.py @@ -0,0 +1,111 @@ +from application_client.kaspa_command_sender import KaspaCommandSender, Errors, InsType, P1, P2 +from application_client.kaspa_message import PersonalMessage +from application_client.kaspa_response_unpacker import unpack_get_public_key_response, unpack_sign_message_response +from ragger.backend import RaisePolicy +from ragger.navigator import NavInsID +from utils import ROOT_SCREENSHOT_PATH, check_signature_validity + +# In this tests we check the behavior of the device when asked to sign a transaction + + +# In this test se send to the device a transaction to sign and validate it on screen +# We will ensure that the displayed information is correct by using screenshots comparison +def test_sign_message_simple(firmware, backend, navigator, test_name): + # Use the app interface instead of raw interface + client = KaspaCommandSender(backend) + # The path used for this entire test + path: str = "m/44'/111111'/0'/1/5" + + # First we need to get the public key of the device in order to build the transaction + rapdu = client.get_public_key(path=path) + _, public_key, _, _ = unpack_get_public_key_response(rapdu.data) + + address_type = 1 + address_index = 5 + message = "Hello Kaspa!" + + message_data = PersonalMessage(address_type, address_index, message) + + # Send the sign device instruction. + # As it requires on-screen validation, the function is asynchronous. + # It will yield the result when the navigation is done + with client.sign_message(message_data=message_data): + # Validate the on-screen request by performing the navigation appropriate for this device + if firmware.device.startswith("nano"): + navigator.navigate_until_text_and_compare(NavInsID.RIGHT_CLICK, + [NavInsID.BOTH_CLICK], + "Approve", + ROOT_SCREENSHOT_PATH, + test_name) + else: + navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP, + [NavInsID.USE_CASE_REVIEW_CONFIRM, + NavInsID.USE_CASE_STATUS_DISMISS], + "Hold to sign", + ROOT_SCREENSHOT_PATH, + test_name) + + # The device as yielded the result, parse it and ensure that the signature is correct + response = client.get_async_response().data + _, der_sig, _, message_hash = unpack_sign_message_response(response) + + assert message_hash == message_data.to_hash() + assert check_signature_validity(public_key, der_sig, message_hash) + +def test_sign_message_kanji(firmware, backend, navigator, test_name): + # Use the app interface instead of raw interface + client = KaspaCommandSender(backend) + # The path used for this entire test + path: str = "m/44'/111111'/0'/1/3" + + # First we need to get the public key of the device in order to build the transaction + rapdu = client.get_public_key(path=path) + _, public_key, _, _ = unpack_get_public_key_response(rapdu.data) + + address_type = 1 + address_index = 3 + message = "こんにちは世界" + + message_data = PersonalMessage(address_type, address_index, message) + + # Send the sign device instruction. + # As it requires on-screen validation, the function is asynchronous. + # It will yield the result when the navigation is done + with client.sign_message(message_data=message_data): + # Validate the on-screen request by performing the navigation appropriate for this device + if firmware.device.startswith("nano"): + navigator.navigate_until_text_and_compare(NavInsID.RIGHT_CLICK, + [NavInsID.BOTH_CLICK], + "Approve", + ROOT_SCREENSHOT_PATH, + test_name) + else: + navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP, + [NavInsID.USE_CASE_REVIEW_CONFIRM, + NavInsID.USE_CASE_STATUS_DISMISS], + "Hold to sign", + ROOT_SCREENSHOT_PATH, + test_name) + + # The device as yielded the result, parse it and ensure that the signature is correct + response = client.get_async_response().data + _, der_sig, _, message_hash = unpack_sign_message_response(response) + + assert message_hash == message_data.to_hash() + assert check_signature_validity(public_key, der_sig, message_hash) + +def test_sign_message_too_long(firmware, backend, navigator, test_name): + backend.raise_policy = RaisePolicy.RAISE_NOTHING + # Use the app interface instead of raw interface + client = KaspaCommandSender(backend) + + address_type = 1 + address_index = 4 + message = '''Lorem ipsum dolor sit amet. Aut omnis amet id voluptatem eligendi sit accusantium dolorem 33 corrupti necessitatibus hic consequatur quod et maiores alias non molestias suscipit? Est voluptatem magni qui odit eius est eveniet cupiditate id eius quae''' + + message_data = PersonalMessage(address_type, address_index, message) + + last_response = client.send_raw_apdu(InsType.SIGN_MESSAGE, p1=P1.P1_INPUTS, p2=P2.P2_LAST, data=message_data.serialize()) + + assert last_response.status == Errors.SW_MESSAGE_TOO_LONG + \ No newline at end of file diff --git a/tests/utils.py b/tests/utils.py index 76b26f9..8a6b511 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,12 +2,10 @@ from secp256k1 import PublicKey -from application_client.kaspa_transaction import Transaction - ROOT_SCREENSHOT_PATH = Path(__file__).parent.resolve() # Check if a signature of a given message is valid -def check_signature_validity(public_key: bytes, signature: bytes, sighash: bytes, transaction: Transaction) -> bool: +def check_signature_validity(public_key: bytes, signature: bytes, sighash: bytes) -> bool: pkey = PublicKey(public_key, True) return pkey.schnorr_verify(sighash, signature, None, True) From bb1d5ad73cae19d17f77db2e1fa92e0a7d716ecc Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Thu, 14 Sep 2023 23:00:40 -0600 Subject: [PATCH 4/9] Implement for Stax --- src/common/bip32.c | 95 -------------- src/common/bip32.h | 70 ---------- src/ui/nbgl_display_message.c | 122 ++++++++++++++++++ .../stax/test_sign_message_kanji/00000.png | Bin 0 -> 7884 bytes .../stax/test_sign_message_kanji/00001.png | Bin 0 -> 9114 bytes .../stax/test_sign_message_kanji/00002.png | Bin 0 -> 9406 bytes .../stax/test_sign_message_kanji/00003.png | Bin 0 -> 5084 bytes .../stax/test_sign_message_kanji/00004.png | Bin 0 -> 10839 bytes .../stax/test_sign_message_simple/00000.png | Bin 0 -> 7884 bytes .../stax/test_sign_message_simple/00001.png | Bin 0 -> 10706 bytes .../stax/test_sign_message_simple/00002.png | Bin 0 -> 9406 bytes .../stax/test_sign_message_simple/00003.png | Bin 0 -> 5084 bytes .../stax/test_sign_message_simple/00004.png | Bin 0 -> 10839 bytes 13 files changed, 122 insertions(+), 165 deletions(-) delete mode 100644 src/common/bip32.c delete mode 100644 src/common/bip32.h create mode 100644 src/ui/nbgl_display_message.c create mode 100644 tests/snapshots/stax/test_sign_message_kanji/00000.png create mode 100644 tests/snapshots/stax/test_sign_message_kanji/00001.png create mode 100644 tests/snapshots/stax/test_sign_message_kanji/00002.png create mode 100644 tests/snapshots/stax/test_sign_message_kanji/00003.png create mode 100644 tests/snapshots/stax/test_sign_message_kanji/00004.png create mode 100644 tests/snapshots/stax/test_sign_message_simple/00000.png create mode 100644 tests/snapshots/stax/test_sign_message_simple/00001.png create mode 100644 tests/snapshots/stax/test_sign_message_simple/00002.png create mode 100644 tests/snapshots/stax/test_sign_message_simple/00003.png create mode 100644 tests/snapshots/stax/test_sign_message_simple/00004.png diff --git a/src/common/bip32.c b/src/common/bip32.c deleted file mode 100644 index 18a4af7..0000000 --- a/src/common/bip32.c +++ /dev/null @@ -1,95 +0,0 @@ -/***************************************************************************** - * MIT License - * - * Copyright (c) 2023 coderofstuff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#include // snprintf -#include // memset, strlen -#include // size_t -#include // uint*_t -#include // bool - -#include "bip32.h" -#include "read.h" - -bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len) { - if (out_len == 0 || out_len > MAX_BIP32_PATH) { - return false; - } - - size_t offset = 0; - - for (size_t i = 0; i < out_len; i++) { - if (offset > in_len) { - return false; - } - out[i] = read_u32_be(in, offset); - offset += 4; - } - - return true; -} - -bool bip32_path_format(const uint32_t *bip32_path, - size_t bip32_path_len, - char *out, - size_t out_len) { - if (bip32_path_len == 0 || bip32_path_len > MAX_BIP32_PATH) { - return false; - } - - size_t offset = 0; - - for (uint16_t i = 0; i < bip32_path_len; i++) { - size_t written; - - snprintf(out + offset, out_len - offset, "%d", bip32_path[i] & 0x7FFFFFFFu); - written = strlen(out + offset); - if (written == 0 || written >= out_len - offset) { - memset(out, 0, out_len); - return false; - } - offset += written; - - if ((bip32_path[i] & 0x80000000u) != 0) { - snprintf(out + offset, out_len - offset, "'"); - written = strlen(out + offset); - if (written == 0 || written >= out_len - offset) { - memset(out, 0, out_len); - return false; - } - offset += written; - } - - if (i != bip32_path_len - 1) { - snprintf(out + offset, out_len - offset, "/"); - written = strlen(out + offset); - if (written == 0 || written >= out_len - offset) { - memset(out, 0, out_len); - return false; - } - offset += written; - } - } - - return true; -} diff --git a/src/common/bip32.h b/src/common/bip32.h deleted file mode 100644 index c306956..0000000 --- a/src/common/bip32.h +++ /dev/null @@ -1,70 +0,0 @@ -/***************************************************************************** - * MIT License - * - * Copyright (c) 2023 coderofstuff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ -#pragma once - -#include // size_t -#include // uint*_t -#include // bool - -/** - * Maximum length of BIP32 path allowed. - */ -#define MAX_BIP32_PATH 5 - -/** - * Read BIP32 path from byte buffer. - * - * @param[in] in - * Pointer to input byte buffer. - * @param[in] in_len - * Length of input byte buffer. - * @param[out] out - * Pointer to output 32-bit integer buffer. - * @param[in] out_len - * Number of BIP32 paths read in the output buffer. - * - * @return true if success, false otherwise. - * - */ -bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len); - -/** - * Format BIP32 path as string. - * - * @param[in] bip32_path - * Pointer to 32-bit integer input buffer. - * @param[in] bip32_path_len - * Maximum number of BIP32 paths in the input buffer. - * @param[out] out string - * Pointer to output string. - * @param[in] out_len - * Length of the output string. - * - * @return true if success, false otherwise. - * - */ -bool bip32_path_format(const uint32_t *bip32_path, - size_t bip32_path_len, - char *out, - size_t out_len); diff --git a/src/ui/nbgl_display_message.c b/src/ui/nbgl_display_message.c new file mode 100644 index 0000000..c32a6c8 --- /dev/null +++ b/src/ui/nbgl_display_message.c @@ -0,0 +1,122 @@ +/***************************************************************************** + * MIT License + * + * Copyright (c) 2023 coderofstuff + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ +#ifdef HAVE_NBGL + +#pragma GCC diagnostic ignored "-Wformat-invalid-specifier" // snprintf +#pragma GCC diagnostic ignored "-Wformat-extra-args" // snprintf + +#include // bool +#include // memset + +#include "os.h" +#include "glyphs.h" +#include "nbgl_use_case.h" + +#include "display.h" +#include "constants.h" +#include "../globals.h" +#include "io.h" +#include "../sw.h" +#include "../address.h" +#include "action/validate.h" +#include "../types.h" +#include "../transaction/types.h" +#include "bip32.h" +#include "../common/format.h" +#include "../menu.h" + +static char g_message[MAX_MESSAGE_LEN]; +static char g_bip32_path[60]; + +static nbgl_layoutTagValue_t pairs[2]; +static nbgl_layoutTagValueList_t pairList; +static nbgl_pageInfoLongPress_t infoLongPress; + +static void confirm_message_rejection(void) { + // display a status page and go back to main + validate_message(false); + nbgl_useCaseStatus("Message signing\ncancelled", false, ui_menu_main); +} + +static void confirm_message_approval(void) { + // display a success status page and go back to main + validate_message(true); + nbgl_useCaseStatus("MESSAGE\nSIGNED", true, ui_menu_main); +} + +static void review_message_choice(bool confirm) { + if (confirm) { + confirm_message_approval(); + } else { + confirm_message_rejection(); + } +} + +static void continue_message_review(void) { + // Fill pairs + pairs[0].item = "BIP32 Path"; + pairs[0].value = g_bip32_path; + pairs[1].item = "Message"; + pairs[1].value = g_message; + + // Setup list + pairList.nbMaxLinesForValue = 0; + pairList.nbPairs = 2; + pairList.pairs = pairs; + + // Info long press + infoLongPress.icon = &C_stax_app_kaspa_64px; + infoLongPress.text = "Sign message"; + infoLongPress.longPressText = "Hold to sign"; + + nbgl_useCaseStaticReview(&pairList, &infoLongPress, "Reject message", review_message_choice); +} + +int ui_display_message() { + if (G_context.req_type != CONFIRM_MESSAGE || G_context.state != STATE_NONE) { + G_context.state = STATE_NONE; + return io_send_sw(SW_BAD_STATE); + } + + memset(g_bip32_path, 0, sizeof(g_bip32_path)); + if (!bip32_path_format(G_context.bip32_path, + G_context.bip32_path_len, + g_bip32_path, + sizeof(g_bip32_path))) { + return io_send_sw(SW_DISPLAY_BIP32_PATH_FAIL); + } + + memset(g_message, 0, sizeof(g_message)); + snprintf(g_message, sizeof(g_message), "%.*s", G_context.msg_info.message_len, G_context.msg_info.message); + + nbgl_useCaseReviewStart(&C_stax_app_kaspa_64px, + "Sign Message", + NULL, + "Cancel", + continue_message_review, + confirm_message_rejection); + return 0; +} + +#endif diff --git a/tests/snapshots/stax/test_sign_message_kanji/00000.png b/tests/snapshots/stax/test_sign_message_kanji/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..ef8c0f1575e871ea832d4dd46cf0af81c2a00c36 GIT binary patch literal 7884 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 QEA^VQPVT4bPlVj~578&LjQ{`u literal 0 HcmV?d00001 diff --git a/tests/snapshots/stax/test_sign_message_kanji/00001.png b/tests/snapshots/stax/test_sign_message_kanji/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..ea783c27f478b70ba41fbc8002b66fed8f65ac68 GIT binary patch literal 9114 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 H<{$q7Rc`{1 literal 0 HcmV?d00001 diff --git a/tests/snapshots/stax/test_sign_message_kanji/00002.png b/tests/snapshots/stax/test_sign_message_kanji/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..c428ef3e4d8837bb678787564b274d523cc35969 GIT binary patch literal 9406 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 literal 0 HcmV?d00001 diff --git a/tests/snapshots/stax/test_sign_message_kanji/00003.png b/tests/snapshots/stax/test_sign_message_kanji/00003.png new file mode 100644 index 0000000000000000000000000000000000000000..c1a8fd4eb09009370b79a8e7d92355e84bad3426 GIT binary patch literal 5084 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 literal 0 HcmV?d00001 diff --git a/tests/snapshots/stax/test_sign_message_simple/00000.png b/tests/snapshots/stax/test_sign_message_simple/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..ef8c0f1575e871ea832d4dd46cf0af81c2a00c36 GIT binary patch literal 7884 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 QEA^VQPVT4bPlVj~578&LjQ{`u literal 0 HcmV?d00001 diff --git a/tests/snapshots/stax/test_sign_message_simple/00001.png b/tests/snapshots/stax/test_sign_message_simple/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..327244e4a97327ef626c13b916a3cd7780c274d6 GIT binary patch literal 10706 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�$Vyq27xuF1uR<=nCmAPYpQ^|r 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 literal 0 HcmV?d00001 diff --git a/tests/snapshots/stax/test_sign_message_simple/00002.png b/tests/snapshots/stax/test_sign_message_simple/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..c428ef3e4d8837bb678787564b274d523cc35969 GIT binary patch literal 9406 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 literal 0 HcmV?d00001 diff --git a/tests/snapshots/stax/test_sign_message_simple/00003.png b/tests/snapshots/stax/test_sign_message_simple/00003.png new file mode 100644 index 0000000000000000000000000000000000000000..c1a8fd4eb09009370b79a8e7d92355e84bad3426 GIT binary patch literal 5084 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 literal 0 HcmV?d00001 From 6bcf2f58c5becd402c9af7bb9945d91337362f63 Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:09:02 -0600 Subject: [PATCH 5/9] python lint --- tests/application_client/kaspa_command_sender.py | 2 +- tests/application_client/kaspa_message.py | 8 ++------ tests/application_client/kaspa_response_unpacker.py | 12 ++++++------ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/tests/application_client/kaspa_command_sender.py b/tests/application_client/kaspa_command_sender.py index 23502aa..74b4530 100644 --- a/tests/application_client/kaspa_command_sender.py +++ b/tests/application_client/kaspa_command_sender.py @@ -140,7 +140,7 @@ def sign_tx(self, transaction: Transaction) -> Generator[None, None, None]: data=txinput.serialize()) as response: yield response - + @contextmanager def sign_message(self, message_data: PersonalMessage) -> Generator[None, None, None]: with self.backend.exchange_async(cla=CLA, diff --git a/tests/application_client/kaspa_message.py b/tests/application_client/kaspa_message.py index bab4a6f..4fdf59f 100644 --- a/tests/application_client/kaspa_message.py +++ b/tests/application_client/kaspa_message.py @@ -1,9 +1,5 @@ -from io import BytesIO -from typing import Union from hashlib import blake2b -from .kaspa_utils import read, read_uint - def hash_init() -> blake2b: return blake2b(digest_size=32, key=bytes("PersonalMessageSigningHash", "ascii")) @@ -15,7 +11,7 @@ def __init__(self, self.address_type: int = address_type # 1 byte self.address_index:int = address_index # 4 bytes self.message: bytes = bytes(message, 'utf8') # var - + def serialize(self) -> bytes: return b"".join([ self.address_type.to_bytes(1, byteorder="big"), @@ -27,4 +23,4 @@ def serialize(self) -> bytes: def to_hash(self) -> bytes: outer_hash = hash_init() outer_hash.update(self.message) - return outer_hash.digest() \ No newline at end of file + return outer_hash.digest() diff --git a/tests/application_client/kaspa_response_unpacker.py b/tests/application_client/kaspa_response_unpacker.py index ed3a1af..a46f047 100644 --- a/tests/application_client/kaspa_response_unpacker.py +++ b/tests/application_client/kaspa_response_unpacker.py @@ -82,15 +82,15 @@ def unpack_sign_tx_response(response: bytes) -> Tuple[int, int, int, bytes, int, # Unpack from response: # response = der_sig_len (1) # der_sig (64) -# hash_len (1) -# hash (32) -def unpack_sign_message_response(response: bytes) -> Tuple[int, int, int, bytes, int, bytes]: +# mhash_len (1) +# mhash (32) +def unpack_sign_message_response(response: bytes) -> Tuple[int, bytes, int, bytes]: response, der_sig_len, der_sig = pop_size_prefixed_buf_from_buf(response) - response, hash_len, hash = pop_size_prefixed_buf_from_buf(response) + response, mhash_len, mhash = pop_size_prefixed_buf_from_buf(response) assert len(response) == 0 return der_sig_len, \ der_sig, \ - hash_len, \ - hash \ No newline at end of file + mhash_len, \ + mhash From d4b7b4fe0289af94aa8fdc74157c354e68884492 Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:11:17 -0600 Subject: [PATCH 6/9] typo unit test --- unit-tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit-tests/CMakeLists.txt b/unit-tests/CMakeLists.txt index 8a3bc36..e55f8b4 100644 --- a/unit-tests/CMakeLists.txt +++ b/unit-tests/CMakeLists.txt @@ -47,7 +47,7 @@ include_directories(/opt/ledger-secure-sdk/lib_standard_app/) add_executable(test_address test_address.c) add_executable(test_format test_format.c) add_executable(test_sighash test_sighash.c) -add_executable(test_personal_message.h test_personal_message.c) +add_executable(test_personal_message test_personal_message.c) add_executable(test_apdu_parser test_apdu_parser.c) add_executable(test_tx_parser test_tx_parser.c) add_executable(test_tx_utils test_tx_utils.c) From 05940ffbf4c386dfbd0fc9dc9c21f9b260e41268 Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:12:43 -0600 Subject: [PATCH 7/9] c-lint --- src/constants.h | 2 +- src/crypto.c | 2 +- src/handler/sign_msg.c | 2 +- src/handler/sign_msg.h | 2 +- src/helper/send_reponse.c | 4 +++- src/types.h | 28 ++++++++++++++-------------- src/ui/bagl_display.c | 6 +++++- src/ui/nbgl_display_message.c | 6 +++++- 8 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/constants.h b/src/constants.h index 9c4e022..193a013 100644 --- a/src/constants.h +++ b/src/constants.h @@ -44,7 +44,7 @@ #define MAX_APPNAME_LEN 64 /** - * Maximum message length (bytes) + * Maximum message length (bytes) */ #define MAX_MESSAGE_LEN 200 diff --git a/src/crypto.c b/src/crypto.c index 48731b4..53a2c72 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -132,7 +132,7 @@ int crypto_sign_personal_message(void) { G_context.bip32_path_len, &private_key, chain_code); - + BEGIN_TRY { TRY { size_t sig_len = sizeof(G_context.tx_info.signature); diff --git a/src/handler/sign_msg.c b/src/handler/sign_msg.c index bc1c7ec..5700235 100644 --- a/src/handler/sign_msg.c +++ b/src/handler/sign_msg.c @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *****************************************************************************/ -#include // uint*_t +#include // uint*_t #include // memset, explicit_bzero #include "types.h" diff --git a/src/handler/sign_msg.h b/src/handler/sign_msg.h index 9159a7f..f005e10 100644 --- a/src/handler/sign_msg.h +++ b/src/handler/sign_msg.h @@ -23,7 +23,7 @@ *****************************************************************************/ #pragma once -#include // uint*_t +#include // uint*_t #include "buffer.h" diff --git a/src/helper/send_reponse.c b/src/helper/send_reponse.c index 8fe51dc..d9e61fd 100644 --- a/src/helper/send_reponse.c +++ b/src/helper/send_reponse.c @@ -81,7 +81,9 @@ int helper_send_response_personal_message_sig() { // len(sighash) -> 1 byte resp[offset++] = sizeof(G_context.msg_info.message_hash); // sighash -> 32 bytes - memmove(resp + offset, G_context.msg_info.message_hash, sizeof(G_context.msg_info.message_hash)); + memmove(resp + offset, + G_context.msg_info.message_hash, + sizeof(G_context.msg_info.message_hash)); offset += sizeof(G_context.msg_info.message_hash); return io_send_response_pointer(resp, offset, SW_OK); diff --git a/src/types.h b/src/types.h index 7d78fdc..454b86e 100644 --- a/src/types.h +++ b/src/types.h @@ -40,7 +40,7 @@ typedef enum { GET_VERSION = 0x03, /// version of the application GET_APP_NAME = 0x04, /// name of the application GET_PUBLIC_KEY = 0x05, /// public key of corresponding BIP32 path - SIGN_TX = 0x06, /// sign transaction with BIP32 path + SIGN_TX = 0x06, /// sign transaction with BIP32 path SIGN_MESSAGE = 0x07 /// sign a personal message with BIP32 path } command_e; @@ -75,9 +75,9 @@ typedef enum { * Enumeration with user request type. */ typedef enum { - CONFIRM_ADDRESS, /// confirm address derived from public key - CONFIRM_TRANSACTION, /// confirm transaction information - CONFIRM_MESSAGE /// confirm message information + CONFIRM_ADDRESS, /// confirm address derived from public key + CONFIRM_TRANSACTION, /// confirm transaction information + CONFIRM_MESSAGE /// confirm message information } request_type_e; /** @@ -101,15 +101,15 @@ typedef struct { } transaction_ctx_t; /** - * Structure for message signing information context. + * Structure for message signing information context. */ typedef struct { - size_t message_len; /// message length - uint8_t message[128]; /// message bytes - uint8_t message_hash[32]; /// message hash - uint8_t signature[MAX_DER_SIG_LEN]; /// signature of the message - uint8_t address_type; /// address type to use for bip32 path - uint32_t address_index; /// address index to use for bip32 path + size_t message_len; /// message length + uint8_t message[128]; /// message bytes + uint8_t message_hash[32]; /// message hash + uint8_t signature[MAX_DER_SIG_LEN]; /// signature of the message + uint8_t address_type; /// address type to use for bip32 path + uint32_t address_index; /// address index to use for bip32 path } message_sign_ctx_t; /** @@ -118,9 +118,9 @@ typedef struct { typedef struct { state_e state; /// state of the context union { - pubkey_ctx_t pk_info; /// public key context - transaction_ctx_t tx_info; /// transaction context - message_sign_ctx_t msg_info; /// message sign context + pubkey_ctx_t pk_info; /// public key context + transaction_ctx_t tx_info; /// transaction context + message_sign_ctx_t msg_info; /// message sign context }; request_type_e req_type; /// user request uint32_t bip32_path[MAX_BIP32_PATH]; /// BIP32 path diff --git a/src/ui/bagl_display.c b/src/ui/bagl_display.c index 810d37d..6e55f66 100644 --- a/src/ui/bagl_display.c +++ b/src/ui/bagl_display.c @@ -267,7 +267,11 @@ int ui_display_message() { } memset(g_message, 0, sizeof(g_message)); - snprintf(g_message, sizeof(g_message), "%.*s", G_context.msg_info.message_len, G_context.msg_info.message); + snprintf(g_message, + sizeof(g_message), + "%.*s", + G_context.msg_info.message_len, + G_context.msg_info.message); g_validate_callback = &ui_action_validate_message; diff --git a/src/ui/nbgl_display_message.c b/src/ui/nbgl_display_message.c index c32a6c8..dee6e2e 100644 --- a/src/ui/nbgl_display_message.c +++ b/src/ui/nbgl_display_message.c @@ -108,7 +108,11 @@ int ui_display_message() { } memset(g_message, 0, sizeof(g_message)); - snprintf(g_message, sizeof(g_message), "%.*s", G_context.msg_info.message_len, G_context.msg_info.message); + snprintf(g_message, + sizeof(g_message), + "%.*s", + G_context.msg_info.message_len, + G_context.msg_info.message); nbgl_useCaseReviewStart(&C_stax_app_kaspa_64px, "Sign Message", From 6fa2ff683e08268a3ebdf5321ad6a7c95f905090 Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:48:31 -0600 Subject: [PATCH 8/9] Set max message len based on device Nano S can only handle up to 120 len Others 200 and above --- Makefile | 5 ++++- fuzzing/CMakeLists.txt | 2 +- src/constants.h | 5 ----- unit-tests/CMakeLists.txt | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 675a1d9..df9129c 100644 --- a/Makefile +++ b/Makefile @@ -35,10 +35,13 @@ APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)" ifeq ($(TARGET_NAME),TARGET_NANOS) DEFINES += MAX_INPUT_COUNT=15 + DEFINES += MAX_MESSAGE_LEN=120 else ifeq ($(TARGET_NAME),TARGET_STAX) DEFINES += MAX_INPUT_COUNT=128 + DEFINES += MAX_MESSAGE_LEN=200 else DEFINES += MAX_INPUT_COUNT=128 + DEFINES += MAX_MESSAGE_LEN=200 endif # Application source files @@ -76,7 +79,7 @@ VARIANT_PARAM = COIN VARIANT_VALUES = KAS # Enabling DEBUG flag will enable PRINTF and disable optimizations -#DEBUG = 1 +DEBUG = 1 ######################################## # Application custom permissions # diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index f70f1b9..53891ae 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -22,7 +22,7 @@ endif() set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -add_compile_definitions(MAX_INPUT_COUNT=15 USB_SEGMENT_SIZE=64) +add_compile_definitions(MAX_INPUT_COUNT=15 MAX_MESSAGE_LEN=200 USB_SEGMENT_SIZE=64) include(extra/TxParser.cmake) diff --git a/src/constants.h b/src/constants.h index 193a013..151d691 100644 --- a/src/constants.h +++ b/src/constants.h @@ -43,11 +43,6 @@ */ #define MAX_APPNAME_LEN 64 -/** - * Maximum message length (bytes) - */ -#define MAX_MESSAGE_LEN 200 - /** * Maximum signature length (bytes). * Schnorr signatures only have 64 bytes diff --git a/unit-tests/CMakeLists.txt b/unit-tests/CMakeLists.txt index e55f8b4..0842ec4 100644 --- a/unit-tests/CMakeLists.txt +++ b/unit-tests/CMakeLists.txt @@ -33,7 +33,7 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ") endif() -add_compile_definitions(TEST HAVE_HASH HAVE_BLAKE2 HAVE_ECC USB_SEGMENT_SIZE=64 MAX_INPUT_COUNT=15 IO_SEPROXYHAL_BUFFER_SIZE_B=128) +add_compile_definitions(TEST HAVE_HASH HAVE_BLAKE2 HAVE_ECC USB_SEGMENT_SIZE=64 MAX_INPUT_COUNT=15 MAX_MESSAGE_LEN=200 IO_SEPROXYHAL_BUFFER_SIZE_B=128) include_directories(../src) # include_directories(mock_includes) From e95a31903b6f6b9553e262216cec44dc6815df36 Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:49:09 -0600 Subject: [PATCH 9/9] Remove commented code --- src/personal_message.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/personal_message.c b/src/personal_message.c index 1c61569..f9196e1 100644 --- a/src/personal_message.c +++ b/src/personal_message.c @@ -24,15 +24,11 @@ #include #include -// #include "cx.h" - #include "constants.h" #include "./import/blake2-impl.h" #include "./import/blake2b.h" #include "./personal_message.h" -// #include "globals.h" - static int hash_init(blake2b_state* hash, size_t size, uint8_t* key, size_t key_len) { if (key == NULL && key_len != 0) { goto err;