From 2060ee17b56ff874afa5a2804454c8066a3864ac Mon Sep 17 00:00:00 2001 From: Carlos Medeiros Date: Thu, 28 Dec 2023 15:53:01 -0100 Subject: [PATCH] return and apduspec improvements --- CMakeLists.txt | 171 +++++++++++++++++----------------- app/src/apdu_handler.c | 5 +- app/src/common/actions.h | 4 +- app/src/parser_impl.c | 1 - app/src/parser_print_common.c | 53 +---------- app/src/tx_cchain.c | 11 ++- app/src/tx_pchain.c | 11 ++- docs/APDUSPEC.md | 59 +++++++----- 8 files changed, 145 insertions(+), 170 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b213d72..f6341f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,18 @@ -#******************************************************************************* -#* (c) 2018 -2023 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. -#******************************************************************************** +# ******************************************************************************* +# * (c) 2018 -2023 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. +# ******************************************************************************** cmake_minimum_required(VERSION 3.0) project(ledger-flare VERSION 0.0.0) enable_testing() @@ -36,23 +36,23 @@ if(ENABLE_FUZZING) SET(ENABLE_SANITIZERS ON CACHE BOOL "Sanitizer automatically enabled" FORCE) SET(CMAKE_BUILD_TYPE Debug) - if (DEFINED ENV{FUZZ_LOGGING}) + if(DEFINED ENV{FUZZ_LOGGING}) add_definitions(-DFUZZING_LOGGING) message(FATAL_ERROR "Fuzz logging enabled") endif() set(CMAKE_CXX_CLANG_TIDY clang-tidy -checks=-*,bugprone-*,cert-*,clang-analyzer-*,-cert-err58-cpp,misc-*) - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # require at least clang 3.2 - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0) + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0) message(FATAL_ERROR "Clang version must be at least 10.0!") endif() else() message(FATAL_ERROR - "You are using an unsupported compiler! Fuzzing only works with Clang 10.\n" - "1. Install clang-10 \n" - "2. Pass -DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10") + "You are using an unsupported compiler! Fuzzing only works with Clang 10.\n" + "1. Install clang-10 \n" + "2. Pass -DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10") endif() string(APPEND CMAKE_C_FLAGS " -fsanitize=fuzzer-no-link") @@ -75,102 +75,103 @@ endif() include(cmake/conan/CMakeLists.txt) add_subdirectory(cmake/gtest) -set (RETRIEVE_MAJOR_CMD - "cat ${CMAKE_CURRENT_SOURCE_DIR}/app/Makefile.version | grep APPVERSION_M | cut -b 14- | tr -d '\n'" +set(RETRIEVE_MAJOR_CMD + "cat ${CMAKE_CURRENT_SOURCE_DIR}/app/Makefile.version | grep APPVERSION_M | cut -b 14- | tr -d '\n'" ) -set (RETRIEVE_MINOR_CMD - "cat ${CMAKE_CURRENT_SOURCE_DIR}/app/Makefile.version | grep APPVERSION_N | cut -b 14- | tr -d '\n'" +set(RETRIEVE_MINOR_CMD + "cat ${CMAKE_CURRENT_SOURCE_DIR}/app/Makefile.version | grep APPVERSION_N | cut -b 14- | tr -d '\n'" ) execute_process( - COMMAND bash "-c" ${RETRIEVE_MAJOR_CMD} - RESULT_VARIABLE MAJOR_RESULT - OUTPUT_VARIABLE MAJOR_VERSION + COMMAND bash "-c" ${RETRIEVE_MAJOR_CMD} + RESULT_VARIABLE MAJOR_RESULT + OUTPUT_VARIABLE MAJOR_VERSION ) execute_process( - COMMAND bash "-c" ${RETRIEVE_MINOR_CMD} - RESULT_VARIABLE MINOR_RESULT - OUTPUT_VARIABLE MINOR_VERSION + COMMAND bash "-c" ${RETRIEVE_MINOR_CMD} + RESULT_VARIABLE MINOR_RESULT + OUTPUT_VARIABLE MINOR_VERSION ) -message(STATUS "LEDGER_MAJOR_VERSION [${MAJOR_RESULT}]: ${MAJOR_VERSION}" ) -message(STATUS "LEDGER_MINOR_VERSION [${MINOR_RESULT}]: ${MINOR_VERSION}" ) +message(STATUS "LEDGER_MAJOR_VERSION [${MAJOR_RESULT}]: ${MAJOR_VERSION}") +message(STATUS "LEDGER_MINOR_VERSION [${MINOR_RESULT}]: ${MINOR_VERSION}") add_definitions( -DLEDGER_MAJOR_VERSION=${MAJOR_VERSION} -DLEDGER_MINOR_VERSION=${MINOR_VERSION} ) - -############################################################## -############################################################## -# static libs +# ############################################################# +# ############################################################# +# static libs file(GLOB_RECURSE LIB_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/hexutils.c - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/app_mode.c - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/bignum.c - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/hexutils.c - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/zxmacros.c - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/zxformat.c - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/bech32.c - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/segwit_addr.c - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/timeutils.c - #### - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser.c - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/crypto_helper.c - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ripemd160/ripemd160.c - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl_common.c - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_print_common.c - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/tx_cchain.c - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/tx_pchain.c - ) + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/hexutils.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/app_mode.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/bignum.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/hexutils.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/zxmacros.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/zxformat.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/bech32.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/base58.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/segwit_addr.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/timeutils.c + + # ### + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/crypto_helper.c + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ripemd160/ripemd160.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl_common.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_print_common.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/tx_cchain.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/tx_pchain.c +) add_library(app_lib STATIC ${LIB_SRC}) target_include_directories(app_lib PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/include - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/app/common - ${CMAKE_CURRENT_SOURCE_DIR}/app/src - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/lib - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/common - ${CMAKE_CURRENT_SOURCE_DIR}/deps/picohash/ - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ripemd160 - ) - -############################################################## -############################################################## -# Tests + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/include + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/app/common + ${CMAKE_CURRENT_SOURCE_DIR}/app/src + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/lib + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/common + ${CMAKE_CURRENT_SOURCE_DIR}/deps/picohash/ + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ripemd160 +) + +# ############################################################# +# ############################################################# +# Tests file(GLOB_RECURSE TESTS_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp) + ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp) add_executable(unittests ${TESTS_SRC}) target_include_directories(unittests PRIVATE - ${gtest_SOURCE_DIR}/include - ${gmock_SOURCE_DIR}/include - ${CONAN_INCLUDE_DIRS_FMT} - ${CONAN_INCLUDE_DIRS_JSONCPP} - ${CMAKE_CURRENT_SOURCE_DIR}/app/src - ${CMAKE_CURRENT_SOURCE_DIR}/app/src/lib - ${CMAKE_CURRENT_SOURCE_DIR}/deps/ripemd160 - ) + ${gtest_SOURCE_DIR}/include + ${gmock_SOURCE_DIR}/include + ${CONAN_INCLUDE_DIRS_FMT} + ${CONAN_INCLUDE_DIRS_JSONCPP} + ${CMAKE_CURRENT_SOURCE_DIR}/app/src + ${CMAKE_CURRENT_SOURCE_DIR}/app/src/lib + ${CMAKE_CURRENT_SOURCE_DIR}/deps/ripemd160 +) target_link_libraries(unittests PRIVATE - gtest_main - app_lib - CONAN_PKG::fmt - CONAN_PKG::jsoncpp) + gtest_main + app_lib + CONAN_PKG::fmt + CONAN_PKG::jsoncpp) add_compile_definitions(TESTVECTORS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/tests/") add_test(unittests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittests) set_tests_properties(unittests PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) -############################################################## -############################################################## -# Fuzz Targets +# ############################################################# +# ############################################################# +# Fuzz Targets if(ENABLE_FUZZING) set(FUZZ_TARGETS parser_parse - ) + ) foreach(target ${FUZZ_TARGETS}) add_executable(fuzz-${target} ${CMAKE_CURRENT_SOURCE_DIR}/fuzz/${target}.cpp) diff --git a/app/src/apdu_handler.c b/app/src/apdu_handler.c index fd98307..fcd963c 100644 --- a/app/src/apdu_handler.c +++ b/app/src/apdu_handler.c @@ -42,7 +42,6 @@ void extractHDPath(uint32_t rx, uint32_t offset) { memcpy(hdPath, G_io_apdu_buffer + offset, sizeof(uint32_t) * HDPATH_LEN_DEFAULT); - // #{TODO} --> testnet necessary? const bool mainnet = hdPath[0] == HDPATH_0_DEFAULT && hdPath[1] == HDPATH_1_DEFAULT; if (!mainnet) { @@ -116,7 +115,7 @@ __Z_INLINE void handleGetAddr(volatile uint32_t *flags, volatile uint32_t *tx, u const uint8_t requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; - zxerr_t zxerr = app_fill_address(); + const zxerr_t zxerr = app_fill_address(); if (zxerr != zxerr_ok) { *tx = 0; THROW(APDU_CODE_DATA_INVALID); @@ -139,7 +138,7 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint THROW(APDU_CODE_OK); } - // GET addres to test later which outputs the app should show + // GET address to test later which outputs the app should show zxerr_t zxerr = app_get_address(); if (zxerr != zxerr_ok) { *tx = 0; diff --git a/app/src/common/actions.h b/app/src/common/actions.h index 5e1e5a6..baf2bfc 100644 --- a/app/src/common/actions.h +++ b/app/src/common/actions.h @@ -33,7 +33,7 @@ __Z_INLINE zxerr_t app_fill_address() { MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); action_addrResponseLen = 0; - zxerr_t err = crypto_fillAddress(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE, &action_addrResponseLen); + const zxerr_t err = crypto_fillAddress(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE, &action_addrResponseLen); if (err != zxerr_ok || action_addrResponseLen == 0) { THROW(APDU_CODE_EXECUTION_ERROR); @@ -76,7 +76,7 @@ __Z_INLINE void app_reply_error() { __Z_INLINE zxerr_t app_get_address() { zemu_log("app_get_address\n"); - zxerr_t err = crypto_get_address(); + const zxerr_t err = crypto_get_address(); if (err != zxerr_ok) { THROW(APDU_CODE_EXECUTION_ERROR); diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index a10495c..d7d6f86 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -159,7 +159,6 @@ parser_error_t getNumItems(const parser_context_t *ctx, uint8_t *numItems) { // Tx + fee + Amounts(= n_outs) + Addresses *numItems = 2 + ctx->tx_obj->tx.p_export_tx.secp_outs.n_addrs + parser_get_renderable_outputs_number(ctx->tx_obj->tx.p_export_tx.secp_outs.out_render_mask); - ; break; case p_import_tx: // Tx + fee + Amounts(= n_outs) + Addresses diff --git a/app/src/parser_print_common.c b/app/src/parser_print_common.c index 4b2eb95..8959b46 100644 --- a/app/src/parser_print_common.c +++ b/app/src/parser_print_common.c @@ -15,6 +15,7 @@ ********************************************************************************/ #include "parser_print_common.h" +#include "base58.h" #include "bech32.h" #include "parser_common.h" #include "timeutils.h" @@ -147,53 +148,6 @@ parser_error_t printTimestamp(uint64_t timestamp, char *outVal, uint16_t outValL return parser_ok; } -static parser_error_t bs58_encode(const uint8_t *input, size_t input_len, uint8_t *output, size_t output_len) { - if (input == NULL || output == NULL) { - return parser_unexpected_error; - } - - const size_t alphabet_size = 58; - const uint8_t *table = (const uint8_t *)ALPHABET_ENCODE; - - size_t index = 0; - for (size_t i = 0; i < input_len; ++i) { - size_t carry = input[i]; - for (size_t j = 0; j < index; ++j) { - carry += output[j] << 8; - output[j] = carry % alphabet_size; - carry /= alphabet_size; - } - while (carry > 0) { - if (index == output_len) { - return parser_unexpected_error; // Output buffer too small - } - output[index++] = carry % alphabet_size; - carry /= alphabet_size; - } - } - - for (size_t i = 0; i < input_len && input[i] == 0; ++i) { - if (index == output_len) { - return parser_unexpected_error; // Output buffer too small - } - output[index++] = 0; - } - - for (size_t i = 0; i < index; ++i) { - output[i] = table[output[i]]; - } - - // Reverse the output - for (size_t i = 0, j = index - 1; i < j; ++i, --j) { - uint8_t temp = output[i]; - output[i] = output[j]; - output[j] = temp; - } - - return parser_ok; - ; -} - parser_error_t printNodeId(const uint8_t *nodeId, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) { if (nodeId == NULL) { return parser_unexpected_error; @@ -223,11 +177,10 @@ parser_error_t printNodeId(const uint8_t *nodeId, char *outVal, uint16_t outValL // Prepare node_id by appending prefix uint8_t node_id[NODE_ID_MAX_SIZE] = {0}; + size_t outlen = sizeof(node_id) - sizeof(prefix) + 1; memcpy(node_id, prefix, sizeof(prefix) - 1); - CHECK_ERROR(bs58_encode((const uint8_t *)data, sizeof(data), node_id + sizeof(prefix) - 1, - sizeof(node_id) - sizeof(prefix) + 1)); - + CHECK_ERROR(encode_base58((const unsigned char *)data, sizeof(data), node_id + sizeof(prefix) - 1, &outlen)) pageString(outVal, outValLen, (const char *)node_id, pageIdx, pageCount); return parser_ok; diff --git a/app/src/tx_cchain.c b/app/src/tx_cchain.c index f29248e..6b210e9 100644 --- a/app/src/tx_cchain.c +++ b/app/src/tx_cchain.c @@ -97,6 +97,7 @@ parser_error_t parser_cchain(parser_context_t *c, parser_tx_t *v) { return parser_handle_cchain_import(c, v); break; default: + return parser_unexpected_type; break; } @@ -110,6 +111,7 @@ parser_error_t print_c_export_tx(const parser_context_t *ctx, uint8_t displayIdx char chain = 0; CHECK_ERROR(parser_get_chain_alias(ctx->tx_obj->tx.c_export_tx.destination_chain, &chain)); snprintf(outVal, outValLen, "C to %c chain", chain); + return parser_ok; } // print ampount and addresses @@ -137,6 +139,7 @@ parser_error_t print_c_export_tx(const parser_context_t *ctx, uint8_t displayIdx snprintf(outKey, outKeyLen, "Address"); CHECK_ERROR(printAddress(address, ctx->tx_obj->network_id, outVal, outValLen, pageIdx, pageCount)); } + return parser_ok; } if (displayIdx == ctx->tx_obj->tx.c_export_tx.secp_outs.n_addrs + @@ -145,9 +148,10 @@ parser_error_t print_c_export_tx(const parser_context_t *ctx, uint8_t displayIdx uint64_t fee = ctx->tx_obj->tx.c_export_tx.evm_inputs.in_sum - ctx->tx_obj->tx.c_export_tx.secp_outs.out_sum; CHECK_ERROR( printAmount64(fee, AMOUNT_DECIMAL_PLACES, ctx->tx_obj->network_id, outVal, outValLen, pageIdx, pageCount)); + return parser_ok; } - return parser_ok; + return parser_display_idx_out_of_range; } parser_error_t print_c_import_tx(const parser_context_t *ctx, uint8_t displayIdx, char *outKey, uint16_t outKeyLen, @@ -157,6 +161,7 @@ parser_error_t print_c_import_tx(const parser_context_t *ctx, uint8_t displayIdx char chain = 0; CHECK_ERROR(parser_get_chain_alias(ctx->tx_obj->tx.c_import_tx.source_chain, &chain)); snprintf(outVal, outValLen, "C from %c chain", chain); + return parser_ok; } // print ampount and addresses @@ -188,6 +193,7 @@ parser_error_t print_c_import_tx(const parser_context_t *ctx, uint8_t displayIdx } pageString(outVal, outValLen, tmp_buffer, pageIdx, pageCount); } + return parser_ok; } if (displayIdx == (2 * ctx->tx_obj->tx.c_import_tx.evm_outs.n_outs) + 1) { @@ -195,7 +201,8 @@ parser_error_t print_c_import_tx(const parser_context_t *ctx, uint8_t displayIdx uint64_t fee = ctx->tx_obj->tx.c_import_tx.secp_inputs.in_sum - ctx->tx_obj->tx.c_import_tx.evm_outs.out_sum; CHECK_ERROR( printAmount64(fee, AMOUNT_DECIMAL_PLACES, ctx->tx_obj->network_id, outVal, outValLen, pageIdx, pageCount)); + return parser_ok; } - return parser_ok; + return parser_display_idx_out_of_range; } diff --git a/app/src/tx_pchain.c b/app/src/tx_pchain.c index c87b3c5..d17551c 100644 --- a/app/src/tx_pchain.c +++ b/app/src/tx_pchain.c @@ -162,6 +162,7 @@ parser_error_t parser_pchain(parser_context_t *c, parser_tx_t *v) { return parser_handle_add_delegator_validator(c, v); break; default: + return parser_unexpected_type; break; } @@ -226,6 +227,7 @@ parser_error_t print_p_export_tx(const parser_context_t *ctx, uint8_t displayIdx char chain = 0; CHECK_ERROR(parser_get_chain_alias(ctx->tx_obj->tx.p_export_tx.destination_chain, &chain)); snprintf(outVal, outValLen, "P to %c chain", chain); + return parser_ok; } // print ampount and addresses @@ -254,6 +256,7 @@ parser_error_t print_p_export_tx(const parser_context_t *ctx, uint8_t displayIdx snprintf(outKey, outKeyLen, "Address"); CHECK_ERROR(printAddress(address, ctx->tx_obj->network_id, outVal, outValLen, pageIdx, pageCount)); } + return parser_ok; } if (displayIdx == ctx->tx_obj->tx.p_export_tx.secp_outs.n_addrs + @@ -263,9 +266,10 @@ parser_error_t print_p_export_tx(const parser_context_t *ctx, uint8_t displayIdx (ctx->tx_obj->tx.p_export_tx.base_secp_outs.out_sum + ctx->tx_obj->tx.p_export_tx.secp_outs.out_sum); CHECK_ERROR( printAmount64(fee, AMOUNT_DECIMAL_PLACES, ctx->tx_obj->network_id, outVal, outValLen, pageIdx, pageCount)); + return parser_ok; } - return parser_ok; + return parser_display_idx_out_of_range; } parser_error_t print_p_import_tx(const parser_context_t *ctx, uint8_t displayIdx, char *outKey, uint16_t outKeyLen, @@ -276,6 +280,7 @@ parser_error_t print_p_import_tx(const parser_context_t *ctx, uint8_t displayIdx char chain = 0; CHECK_ERROR(parser_get_chain_alias(ctx->tx_obj->tx.p_import_tx.source_chain, &chain)); snprintf(outVal, outValLen, "P from %c chain", chain); + return parser_ok; } // print ampount and addresses @@ -304,6 +309,7 @@ parser_error_t print_p_import_tx(const parser_context_t *ctx, uint8_t displayIdx snprintf(outKey, outKeyLen, "Address"); CHECK_ERROR(printAddress(address, ctx->tx_obj->network_id, outVal, outValLen, pageIdx, pageCount)); } + return parser_ok; } if (displayIdx == @@ -313,7 +319,8 @@ parser_error_t print_p_import_tx(const parser_context_t *ctx, uint8_t displayIdx ctx->tx_obj->tx.p_import_tx.base_secp_outs.out_sum; CHECK_ERROR( printAmount64(fee, AMOUNT_DECIMAL_PLACES, ctx->tx_obj->network_id, outVal, outValLen, pageIdx, pageCount)); + return parser_ok; } - return parser_ok; + return parser_display_idx_out_of_range; } diff --git a/docs/APDUSPEC.md b/docs/APDUSPEC.md index 5cc7a95..b7331c8 100644 --- a/docs/APDUSPEC.md +++ b/docs/APDUSPEC.md @@ -2,8 +2,6 @@ ## General structure -# #{TODO} --> Update CLA, HDPATH and APDU messages - The general structure of commands and responses is as follows: ### Commands @@ -29,12 +27,17 @@ The general structure of commands and responses is as follows: | Return code | Description | | ----------- | ----------------------- | | 0x6400 | Execution Error | +| 0x6700 | Wrong buffer length | | 0x6982 | Empty buffer | | 0x6983 | Output buffer too small | +| 0x6984 | Data is invalid | | 0x6986 | Command not allowed | +| 0x6987 | Tx is not initialized | +| 0x6B00 | P1/P2 are invalid | | 0x6D00 | INS not supported | | 0x6E00 | CLA not supported | | 0x6F00 | Unknown | +| 0x6F01 | Sign / verify error | | 0x9000 | Success | --- @@ -51,44 +54,48 @@ The general structure of commands and responses is as follows: | INS | byte (1) | Instruction ID | 0x00 | | P1 | byte (1) | Parameter 1 | ignored | | P2 | byte (1) | Parameter 2 | ignored | -| L | byte (1) | Bytes in payload | 0 | +| L | byte (1) | Bytes in payload | 0x0 | #### Response -| Field | Type | Content | Note | -| ------- | -------- | ---------------- | ------------------------------- | -| TEST | byte (1) | Test Mode | 0xFF means test mode is enabled | -| MAJOR | byte (2) | Version Major | 0..65535 | -| MINOR | byte (2) | Version Minor | 0..65535 | -| PATCH | byte (2) | Version Patch | 0..65535 | -| LOCKED | byte (1) | Device is locked | | -| SW1-SW2 | byte (2) | Return code | see list of return codes | +| Field | Type | Content | Note | +| --------- | -------- | ---------------- | ------------------------------- | +| TEST | byte (1) | Test Mode | 0xFF means test mode is enabled | +| MAJOR | byte (2) | Version Major | 0..65535 | +| MINOR | byte (2) | Version Minor | 0..65535 | +| PATCH | byte (2) | Version Patch | 0..65535 | +| TARGET_ID | byte (4) | Target Id | | +| LOCKED | byte (1) | Device is locked | | +| SW1-SW2 | byte (2) | Return code | see list of return codes | --- ### INS_GET_ADDR +Derivation Path can #### Command -| Field | Type | Content | Expected | -| ------- | -------- | ------------------------- | ---------- | -| CLA | byte (1) | Application Identifier | 0x58 | -| INS | byte (1) | Instruction ID | 0x01 | -| P1 | byte (1) | Request User confirmation | No = 0 | -| P2 | byte (1) | Parameter 2 | ignored | -| L | byte (1) | Bytes in payload | (depends) | -| Path[0] | byte (4) | Derivation Path Data | 0x8000002c | -| Path[1] | byte (4) | Derivation Path Data | 0x80002328 | -| Path[2] | byte (4) | Derivation Path Data | ? | -| Path[3] | byte (4) | Derivation Path Data | ? | -| Path[4] | byte (4) | Derivation Path Data | ? | +| Field | Type | Content | Expected | +| ------- | --------------- | ------------------------- | ----------------- | +| CLA | byte (1) | Application Identifier | 0x58 | +| INS | byte (1) | Instruction ID | 0x01 | +| P1 | byte (1) | Request User confirmation | No = 0 | +| P2 | byte (1) | Parameter 2 | ignored | +| L | byte (1) | Bytes in payload | (depends) | +| HRP_LEN | byte(1) | Bech32 HRP Length | 1<=HRP_LEN<=83 | +| HRP | byte (HRP_LEN) | Bech32 HRP | | +| Path[0] | byte (4) | Derivation Path Data | 0x8000002c | +| Path[1] | byte (4) | Derivation Path Data | 0x80002328 | +| Path[2] | byte (4) | Derivation Path Data | ? | +| Path[3] | byte (4) | Derivation Path Data | ? | +| Path[4] | byte (4) | Derivation Path Data | ? | #### Response | Field | Type | Content | Note | | ------- | --------- | ----------- | ------------------------ | -| PK | byte (20) | Public Key | Compressed public key | -| ADDR | byte (??) | address | CB58 encoded address | +| PK | byte (33) | Public Key | Compressed public key | +| ADDR | byte (??) | address | Bech32 encoded address | | SW1-SW2 | byte (2) | Return code | see list of return codes | --- @@ -118,6 +125,8 @@ All other packets/chunks contain data chunks that are described below | Path[0] | byte (4) | Derivation Path Data | 44 | | Path[1] | byte (4) | Derivation Path Data | 9000 | | Path[2] | byte (4) | Derivation Path Data | ? | +| Path[3] | byte (4) | Derivation Path Data | ? | +| Path[4] | byte (4) | Derivation Path Data | ? | ##### Other Chunks/Packets