Skip to content

Commit

Permalink
Merge pull request #1 from Zondax/feat/m2-parser
Browse files Browse the repository at this point in the history
  • Loading branch information
chcmedeiros authored Jan 2, 2024
2 parents 38b07aa + 07bfa8d commit 38950ca
Show file tree
Hide file tree
Showing 342 changed files with 2,268 additions and 364 deletions.
166 changes: 86 additions & 80 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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")
Expand All @@ -75,97 +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}/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}/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)
Expand Down
2 changes: 1 addition & 1 deletion app/Makefile.version
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ APPVERSION_M=0
# This is the minor version
APPVERSION_N=0
# This is the patch version
APPVERSION_P=2
APPVERSION_P=3
10 changes: 8 additions & 2 deletions app/src/apdu_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -139,6 +138,13 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint
THROW(APDU_CODE_OK);
}

// GET address to test later which outputs the app should show
zxerr_t zxerr = app_get_address();
if (zxerr != zxerr_ok) {
*tx = 0;
THROW(APDU_CODE_DATA_INVALID);
}

const char *error_msg = tx_parse();
CHECK_APP_CANARY()
if (error_msg != NULL) {
Expand Down
5 changes: 5 additions & 0 deletions app/src/coin.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ extern "C" {

#define CLA 0x58

typedef enum {
BECH32 = 0,
UNSUPPORTED = 0xFF,
} address_encoding_e;

#define HDPATH_LEN_DEFAULT 5
#define HDPATH_0_DEFAULT (0x80000000u | 0x2c) // 44
#define HDPATH_1_DEFAULT (0x80000000u | 0x2328) // 9000
Expand Down
14 changes: 13 additions & 1 deletion app/src/common/actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -72,3 +72,15 @@ __Z_INLINE void app_reply_error() {
set_code(G_io_apdu_buffer, 0, APDU_CODE_DATA_INVALID);
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
}

__Z_INLINE zxerr_t app_get_address() {
zemu_log("app_get_address\n");

const zxerr_t err = crypto_get_address();

if (err != zxerr_ok) {
THROW(APDU_CODE_EXECUTION_ERROR);
}

return zxerr_ok;
}
13 changes: 12 additions & 1 deletion app/src/common/parser_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,18 @@ typedef enum {
parser_invalid_address,
parser_unexpected_chain,
parser_missing_field,
paser_unknown_transaction,
parser_unknown_transaction,

// utils specific
parser_unexpected_data_len,
parser_invalid_codec,
parser_unexpected_network,
parser_unexpected_type_id,
parser_unexpected_threshold,
parser_unexpected_unparsed_bytes,
parser_invalid_time_stamp,
parser_invalid_stake_amount,
parser_unexpected_output_locked,
} parser_error_t;

typedef struct {
Expand Down
35 changes: 25 additions & 10 deletions app/src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include "zxmacros.h"

uint32_t hdPath[HDPATH_LEN_DEFAULT];

uint8_t change_address[20];
#include <bech32.h>

#define MAX_DER_SIGNATURE_LEN 73
Expand All @@ -39,11 +39,11 @@ zxerr_t crypto_extractUncompressedPublicKey(uint8_t *pubKey, uint16_t pubKeyLen)
zxerr_t error = zxerr_unknown;

CATCH_CXERROR(os_derive_bip32_with_seed_no_throw(HDW_NORMAL, CX_CURVE_256K1, hdPath, HDPATH_LEN_DEFAULT, privateKeyData,
NULL, NULL, 0))
NULL, NULL, 0));

CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_256K1, privateKeyData, 32, &cx_privateKey))
CATCH_CXERROR(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, NULL, 0, &cx_publicKey))
CATCH_CXERROR(cx_ecfp_generate_pair_no_throw(CX_CURVE_256K1, &cx_publicKey, &cx_privateKey, 1))
CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_256K1, privateKeyData, 32, &cx_privateKey));
CATCH_CXERROR(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, NULL, 0, &cx_publicKey));
CATCH_CXERROR(cx_ecfp_generate_pair_no_throw(CX_CURVE_256K1, &cx_publicKey, &cx_privateKey, 1));
memcpy(pubKey, cx_publicKey.W, PK_LEN_SECP256K1_UNCOMPRESSED);
error = zxerr_ok;

Expand Down Expand Up @@ -88,12 +88,12 @@ zxerr_t crypto_sign(uint8_t *signature, uint16_t signatureMaxlen, uint16_t *sigS

// Generate keys
CATCH_CXERROR(os_derive_bip32_with_seed_no_throw(HDW_NORMAL, CX_CURVE_256K1, hdPath, HDPATH_LEN_DEFAULT, privateKeyData,
NULL, NULL, 0))
CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_256K1, privateKeyData, 32, &cx_privateKey))
NULL, NULL, 0));
CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_256K1, privateKeyData, 32, &cx_privateKey));

// Sign
CATCH_CXERROR(cx_ecdsa_sign_no_throw(&cx_privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256, messageDigest, CX_SHA256_SIZE,
signature, &signatureLength, &info))
signature, &signatureLength, &info));

*sigSize = signatureLength;
error = zxerr_ok;
Expand All @@ -117,8 +117,8 @@ zxerr_t crypto_fillAddress(uint8_t *buffer, uint16_t bufferLen, uint16_t *addrRe

char *addr = (char *)(buffer + PK_LEN_SECP256K1);
uint8_t uncompressedPubkey[PK_LEN_SECP256K1_UNCOMPRESSED] = {0};
CHECK_ZXERR(crypto_extractUncompressedPublicKey(uncompressedPubkey, sizeof(uncompressedPubkey)))
CHECK_ZXERR(compressPubkey(uncompressedPubkey, sizeof(uncompressedPubkey), buffer, bufferLen))
CHECK_ZXERR(crypto_extractUncompressedPublicKey(uncompressedPubkey, sizeof(uncompressedPubkey)));
CHECK_ZXERR(compressPubkey(uncompressedPubkey, sizeof(uncompressedPubkey), buffer, bufferLen));

const uint8_t outLen = crypto_encodePubkey(buffer, addr, bufferLen - PK_LEN_SECP256K1);

Expand All @@ -130,3 +130,18 @@ zxerr_t crypto_fillAddress(uint8_t *buffer, uint16_t bufferLen, uint16_t *addrRe
*addrResponseLen = PK_LEN_SECP256K1 + outLen;
return zxerr_ok;
}

zxerr_t crypto_get_address(void) {
uint8_t uncompressedPubkey[PK_LEN_SECP256K1_UNCOMPRESSED] = {0};
uint8_t compressedPubkey[PK_LEN_SECP256K1] = {0};
CHECK_ZXERR(crypto_extractUncompressedPublicKey(uncompressedPubkey, sizeof(uncompressedPubkey)));
CHECK_ZXERR(compressPubkey(uncompressedPubkey, sizeof(uncompressedPubkey), compressedPubkey, sizeof(compressedPubkey)));

// Hash it
uint8_t hashed1_pk[CX_SHA256_SIZE] = {0};
crypto_sha256(compressedPubkey, PK_LEN_SECP256K1, hashed1_pk, CX_SHA256_SIZE);

CHECK_ZXERR(ripemd160_32(change_address, hashed1_pk))

return zxerr_ok;
}
Loading

0 comments on commit 38950ca

Please sign in to comment.