Skip to content

Commit

Permalink
Merge pull request #4 from Zondax/feat/sign_hash
Browse files Browse the repository at this point in the history
Feat/sign hash
  • Loading branch information
chcmedeiros authored Jan 11, 2024
2 parents 9be0da2 + cb149e6 commit 486a142
Show file tree
Hide file tree
Showing 414 changed files with 411 additions and 73 deletions.
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=5
APPVERSION_P=6
27 changes: 27 additions & 0 deletions app/src/apdu_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "coin.h"
#include "crypto.h"
#include "crypto_helper.h"
#include "hash.h"
#include "tx.h"
#include "view.h"
#include "view_internal.h"
Expand Down Expand Up @@ -159,6 +160,26 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint
*flags |= IO_ASYNCH_REPLY;
}

__Z_INLINE void handleSignHash(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
zemu_log("handleSignHash\n");
if (!process_chunk(tx, rx)) {
THROW(APDU_CODE_OK);
}

const char *error_msg = hash_parse();
CHECK_APP_CANARY()
if (error_msg != NULL) {
const int error_msg_length = strnlen(error_msg, sizeof(G_io_apdu_buffer));
memcpy(G_io_apdu_buffer, error_msg, error_msg_length);
*tx += (error_msg_length);
THROW(APDU_CODE_DATA_INVALID);
}

view_review_init(hash_getItem, hash_getNumItems, app_sign_hash);
view_review_show(REVIEW_TXN);
*flags |= IO_ASYNCH_REPLY;
}

__Z_INLINE void handle_getversion(__Z_UNUSED volatile uint32_t *flags, volatile uint32_t *tx) {
G_io_apdu_buffer[0] = 0;

Expand Down Expand Up @@ -216,6 +237,12 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
handleSign(flags, tx, rx);
break;
}

case INS_SIGN_HASH: {
CHECK_PIN_VALIDATED()
handleSignHash(flags, tx, rx);
break;
}
default:
THROW(APDU_CODE_INS_NOT_SUPPORTED);
}
Expand Down
1 change: 1 addition & 0 deletions app/src/coin.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ typedef enum {
UNSUPPORTED = 0xFF,
} address_encoding_e;

#define INS_SIGN_HASH 0x3
#define HDPATH_LEN_DEFAULT 5
#define HDPATH_0_DEFAULT (0x80000000u | 0x2c) // 44
#define HDPATH_1_DEFAULT (0x80000000u | 0x2328) // 9000
Expand Down
17 changes: 16 additions & 1 deletion app/src/common/actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,22 @@ __Z_INLINE void app_sign() {
uint16_t replyLen = 0;

MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
const zxerr_t err = crypto_sign(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, &replyLen);
const zxerr_t err = crypto_sign(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, &replyLen, false);

if (err != zxerr_ok || replyLen == 0) {
set_code(G_io_apdu_buffer, 0, APDU_CODE_SIGN_VERIFY_ERROR);
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
} else {
set_code(G_io_apdu_buffer, replyLen, APDU_CODE_OK);
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, replyLen + 2);
}
}

__Z_INLINE void app_sign_hash() {
uint16_t replyLen = 0;

MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
const zxerr_t err = crypto_sign(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, &replyLen, true);

if (err != zxerr_ok || replyLen == 0) {
set_code(G_io_apdu_buffer, 0, APDU_CODE_SIGN_VERIFY_ERROR);
Expand Down
8 changes: 6 additions & 2 deletions app/src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ __Z_INLINE zxerr_t compressPubkey(const uint8_t *pubkey, uint16_t pubkeyLen, uin
return zxerr_ok;
}

zxerr_t crypto_sign(uint8_t *signature, uint16_t signatureMaxlen, uint16_t *sigSize) {
zxerr_t crypto_sign(uint8_t *signature, uint16_t signatureMaxlen, uint16_t *sigSize, bool hash) {
if (signature == NULL || sigSize == NULL) {
return zxerr_invalid_crypto_settings;
}
Expand All @@ -78,7 +78,11 @@ zxerr_t crypto_sign(uint8_t *signature, uint16_t signatureMaxlen, uint16_t *sigS
// Hash it
const uint8_t *message = tx_get_buffer();
const uint16_t messageLen = tx_get_buffer_length();
crypto_sha256(message, messageLen, messageDigest, CX_SHA256_SIZE);
if (!hash) {
crypto_sha256(message, messageLen, messageDigest, CX_SHA256_SIZE);
} else {
MEMCPY(messageDigest, message, messageLen);
}

cx_ecfp_private_key_t cx_privateKey = {0};
uint8_t privateKeyData[64] = {0};
Expand Down
2 changes: 1 addition & 1 deletion app/src/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extern uint8_t change_address[20];

zxerr_t crypto_fillAddress(uint8_t *buffer, uint16_t bufferLen, uint16_t *addrResponseLen);

zxerr_t crypto_sign(uint8_t *signature, uint16_t signatureMaxlen, uint16_t *sigSize);
zxerr_t crypto_sign(uint8_t *signature, uint16_t signatureMaxlen, uint16_t *sigSize, bool hash);

zxerr_t crypto_get_address(void);

Expand Down
72 changes: 72 additions & 0 deletions app/src/hash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*******************************************************************************
* (c) 2018 - 2022 Zondax AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
********************************************************************************/

#include <stdio.h>

#include "app_mode.h"
#include "coin.h"
#include "crypto.h"
#include "crypto_helper.h"
#include "parser_impl.h"
#include "tx.h"
#include "zxerror.h"
#include "zxformat.h"
#include "zxmacros.h"

const char *hash_parse() {
const uint8_t *data = tx_get_buffer();
const size_t dataLen = tx_get_buffer_length();
if (data == NULL || dataLen == 0) {
return parser_getErrorDescription(parser_no_data);
}

if (dataLen != 32) {
return parser_getErrorDescription(parser_unexpected_buffer_end);
}
return NULL;
}

zxerr_t hash_getNumItems(uint8_t *num_items) {
zemu_log_stack("hash_getNumItems");
*num_items = 1;
return zxerr_ok;
}

zxerr_t hash_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outVal, uint16_t outValLen, uint8_t pageIdx,
uint8_t *pageCount) {
ZEMU_LOGF(200, "[hash_getItem] %d/%d\n", displayIdx, pageIdx)

MEMZERO(outKey, outKeyLen);
MEMZERO(outVal, outValLen);
snprintf(outKey, outKeyLen, "?");
snprintf(outVal, outValLen, " ");
*pageCount = 1;

const uint8_t *hash = tx_get_buffer();
const uint16_t hashLength = tx_get_buffer_length();

if (hashLength == 0) {
return zxerr_no_data;
}

if (displayIdx == 0) {
snprintf(outKey, outKeyLen, "Hash");
pageStringHex(outVal, outValLen, (const char *)hash, hashLength, pageIdx, pageCount);
return zxerr_ok;
}

return zxerr_no_data;
}
35 changes: 35 additions & 0 deletions app/src/hash.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*******************************************************************************
* (c) 2018 - 2022 Zondax AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
********************************************************************************/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif
#include "zxerror.h"

const char *hash_parse();

// Return the number of items in the address view
zxerr_t hash_getNumItems(uint8_t *num_items);

// Gets an specific item from the address view (including paging)
zxerr_t hash_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, char *outValue, uint16_t outValueLen,
uint8_t pageIdx, uint8_t *pageCount);

#ifdef __cplusplus
}
#endif
17 changes: 11 additions & 6 deletions app/src/parser_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "parser_impl.h"

#include "app_mode.h"
#include "parser_impl_common.h"
#include "tx_cchain.h"
#include "tx_pchain.h"
Expand Down Expand Up @@ -154,31 +155,35 @@ parser_error_t _read(parser_context_t *ctx, parser_tx_t *v) {

parser_error_t getNumItems(const parser_context_t *ctx, uint8_t *numItems) {
*numItems = 0;
const uint8_t expertModeHashField = app_mode_expert() ? 1 : 0;
switch (ctx->tx_obj->tx_type) {
case p_export_tx:
// 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);
parser_get_renderable_outputs_number(ctx->tx_obj->tx.p_export_tx.secp_outs.out_render_mask) +
expertModeHashField;
break;
case p_import_tx:
// Tx + fee + Amounts(= n_outs) + Addresses
*numItems = 2 + ctx->tx_obj->tx.p_import_tx.base_secp_outs.n_addrs +
parser_get_renderable_outputs_number(ctx->tx_obj->tx.p_import_tx.base_secp_outs.out_render_mask);
parser_get_renderable_outputs_number(ctx->tx_obj->tx.p_import_tx.base_secp_outs.out_render_mask) +
expertModeHashField;
break;
case c_export_tx:
// Tx + fee + Amounts(= n_outs) + Addresses
*numItems = 2 + ctx->tx_obj->tx.c_export_tx.secp_outs.n_addrs +
parser_get_renderable_outputs_number(ctx->tx_obj->tx.c_export_tx.secp_outs.out_render_mask);
parser_get_renderable_outputs_number(ctx->tx_obj->tx.c_export_tx.secp_outs.out_render_mask) +
expertModeHashField;
break;
case c_import_tx:
// Tx + fee + (amount + address) * n_outs
*numItems = 2 + (2 * ctx->tx_obj->tx.c_import_tx.evm_outs.n_outs);
*numItems = 2 + (2 * ctx->tx_obj->tx.c_import_tx.evm_outs.n_outs) + expertModeHashField;
break;
case add_delegator_tx:
*numItems = 6;
*numItems = 6 + expertModeHashField;
break;
case add_validator_tx:
*numItems = 7;
*numItems = 7 + expertModeHashField;
break;
default:
break;
Expand Down
1 change: 1 addition & 0 deletions app/src/parser_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extern "C" {

parser_error_t _read(parser_context_t *ctx, parser_tx_t *v);
parser_error_t getNumItems(const parser_context_t *ctx, uint8_t *numItems);
const char *parser_getErrorDescription(parser_error_t err);
#ifdef __cplusplus
}
#endif
19 changes: 19 additions & 0 deletions app/src/parser_print_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,22 @@ parser_error_t printNodeId(const uint8_t *nodeId, char *outVal, uint16_t outValL

return parser_ok;
}

parser_error_t printHash(const parser_context_t *ctx, char *outVal, uint16_t outValLen, uint8_t pageIdx,
uint8_t *pageCount) {
unsigned char hash[CX_SHA256_SIZE] = {0};

#if defined(TARGET_NANOS) || defined(TARGET_NANOS2) || defined(TARGET_NANOX) || defined(TARGET_STAX)
cx_sha256_t hash_ctx;
memset(&hash_ctx, 0, sizeof(hash_ctx));
CHECK_CX_PARSER_OK(cx_sha256_init_no_throw(&hash_ctx));
CHECK_CX_PARSER_OK(cx_hash_no_throw(&hash_ctx.header, CX_LAST, ctx->buffer, ctx->bufferLen, hash, sizeof(hash)));
#else
picohash_ctx_t hash_ctx;
picohash_init_sha256(&hash_ctx);
picohash_update(&hash_ctx, ctx->buffer, ctx->bufferLen);
picohash_final(&hash_ctx, &hash);
#endif
pageStringHex(outVal, outValLen, (const char *)hash, sizeof(hash), pageIdx, pageCount);
return parser_ok;
}
1 change: 1 addition & 0 deletions app/src/parser_print_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ parser_error_t printTimestamp(uint64_t timestamp, char *outVal, uint16_t outValL

parser_error_t printNodeId(const uint8_t *nodeId, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount);

parser_error_t printHash(const parser_context_t *ctx, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount);
#ifdef __cplusplus
}

Expand Down
14 changes: 14 additions & 0 deletions app/src/tx_cchain.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ parser_error_t print_c_export_tx(const parser_context_t *ctx, uint8_t displayIdx
return parser_ok;
}

if (displayIdx == ctx->tx_obj->tx.c_export_tx.secp_outs.n_addrs +
parser_get_renderable_outputs_number(ctx->tx_obj->tx.c_export_tx.secp_outs.out_render_mask) + 1 +
1) {
snprintf(outKey, outKeyLen, "Hash");
printHash(ctx, outVal, outValLen, pageIdx, pageCount);
return parser_ok;
}

return parser_display_idx_out_of_range;
}

Expand Down Expand Up @@ -209,5 +217,11 @@ parser_error_t print_c_import_tx(const parser_context_t *ctx, uint8_t displayIdx
return parser_ok;
}

if (displayIdx == (2 * ctx->tx_obj->tx.c_import_tx.evm_outs.n_outs) + 1 + 1) {
snprintf(outKey, outKeyLen, "Hash");
printHash(ctx, outVal, outValLen, pageIdx, pageCount);
return parser_ok;
}

return parser_display_idx_out_of_range;
}
23 changes: 22 additions & 1 deletion app/src/tx_pchain.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
********************************************************************************/
#include "tx_pchain.h"

#include "app_mode.h"
#include "parser_impl_common.h"
#include "parser_print_common.h"
#include "zxformat.h"
Expand Down Expand Up @@ -180,7 +181,7 @@ parser_error_t parser_pchain(parser_context_t *c, parser_tx_t *v) {

parser_error_t print_add_del_val_tx(const parser_context_t *ctx, uint8_t displayIdx, char *outKey, uint16_t outKeyLen,
char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) {
if (ctx->tx_obj->tx_type == add_delegator_tx && displayIdx == 5) {
if (ctx->tx_obj->tx_type == add_delegator_tx && displayIdx >= 5) {
displayIdx += 1;
}

Expand Down Expand Up @@ -222,6 +223,11 @@ parser_error_t print_add_del_val_tx(const parser_context_t *ctx, uint8_t display
printAmount64(fee, AMOUNT_DECIMAL_PLACES, ctx->tx_obj->network_id, outVal, outValLen, pageIdx, pageCount));
break;
default:
if (app_mode_expert() && displayIdx == 7) {
snprintf(outKey, outKeyLen, "Hash");
printHash(ctx, outVal, outValLen, pageIdx, pageCount);
return parser_ok;
}
return parser_display_idx_out_of_range;
}

Expand Down Expand Up @@ -277,6 +283,14 @@ parser_error_t print_p_export_tx(const parser_context_t *ctx, uint8_t displayIdx
return parser_ok;
}

if (displayIdx == 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) + 1 +
1) {
snprintf(outKey, outKeyLen, "Hash");
printHash(ctx, outVal, outValLen, pageIdx, pageCount);
return parser_ok;
}

return parser_display_idx_out_of_range;
}

Expand Down Expand Up @@ -330,5 +344,12 @@ parser_error_t print_p_import_tx(const parser_context_t *ctx, uint8_t displayIdx
return parser_ok;
}

if (displayIdx ==
ctx->tx_obj->tx.p_import_tx.base_secp_outs.n_addrs + ctx->tx_obj->tx.p_import_tx.base_secp_outs.n_outs + 1 + 1) {
snprintf(outKey, outKeyLen, "Hash");
printHash(ctx, outVal, outValLen, pageIdx, pageCount);
return parser_ok;
}

return parser_display_idx_out_of_range;
}
Loading

0 comments on commit 486a142

Please sign in to comment.