Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 0 additions & 166 deletions APP_SPECIFICATION.md

This file was deleted.

7 changes: 4 additions & 3 deletions doc/APP_SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,10 @@ The following standard Status Words are returned for all APDUs.
| B003 | SW_DISPLAY_AMOUNT_FAIL | Amount conversion to string failed |
| B004 | SW_WRONG_TX_LENGTH | Wrong raw transaction length |
| B005 | SW_TX_PARSING_FAIL | Failed to parse raw transaction |
| B006 | SW_TX_HASH_FAIL | Failed to compute hash digest of raw transaction |
| B006 | SW_HASH_FAIL | Failed to compute hash digest of raw transaction or msg |
| B007 | SW_BAD_STATE | Security issue with bad state |
| B008 | SW_SIGNATURE_FAIL | Signature of data(tx or personal msg) failed |
| B009 | SW_PERSONAL_MSG_PARSING_FAIL | Failed to parse personal msg |
| B00A | SW_PERSONAL_MSG_HASH_FAIL | Failed to compute hash digest of personal msg |
| B00B | SW_INVALID_TRANSACTION | Invalid transaction |
| B00A | SW_INVALID_TRANSACTION | Invalid transaction |
| B00B | SW_HASH_FAILED | Msg hash failed |
| B00C | SW_INVALID_PATH | Invalid path |
5 changes: 5 additions & 0 deletions src/handler/get_public_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "sw.h"
#include "display.h"
#include "send_response.h"
#include "../transaction/utils.h"

int handler_get_public_key(buffer_t *cdata, bool display) {
explicit_bzero(&G_context, sizeof(G_context));
Expand All @@ -43,6 +44,10 @@ int handler_get_public_key(buffer_t *cdata, bool display) {
return io_send_sw(SW_WRONG_DATA_LENGTH);
}

if (!is_valid_bip44_prefix(G_context.bip32_path, G_context.bip32_path_len)) {
return io_send_sw(SW_INVALID_PATH);
}

cx_err_t error = bip32_derive_get_pubkey_256(CX_CURVE_256R1,
G_context.bip32_path,
G_context.bip32_path_len,
Expand Down
7 changes: 5 additions & 2 deletions src/handler/sign_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,16 @@ int handler_sign_message(buffer_t *cdata, uint8_t chunk, bool more) {
(size_t) G_context.bip32_path_len)) {
return io_send_sw(SW_WRONG_DATA_LENGTH);
}
if (!is_valid_bip44_prefix(G_context.bip32_path, G_context.bip32_path_len)) {
return io_send_sw(SW_INVALID_PATH);
}
return io_send_sw(SW_OK);
} else {
if (G_context.req_type != CONFIRM_MESSAGE) {
return io_send_sw(SW_BAD_STATE);
}
if (G_context.msg_info.raw_msg_len + cdata->size > sizeof(G_context.msg_info.raw_msg)) {
return io_send_sw(SW_WRONG_PERSONAL_MSG_LENGTH);
return io_send_sw(SW_WRONG_DATA_LENGTH);
}
if (!buffer_move(cdata,
G_context.msg_info.raw_msg + G_context.msg_info.raw_msg_len,
Expand Down Expand Up @@ -79,7 +82,7 @@ int handler_sign_message(buffer_t *cdata, uint8_t chunk, bool more) {
G_context.msg_info.raw_msg,
G_context.msg_info.raw_msg_len) != CX_OK ||
cx_hash_final((cx_hash_t *) &cx_sha256, G_context.msg_info.m_hash) != CX_OK) {
return io_send_sw(SW_WRONG_PERSONAL_MSG_LENGTH); // todo, another sw
return io_send_sw(SW_HASH_FAIL);
}

PRINTF("Hash: %.*H\n", sizeof(G_context.msg_info.m_hash), G_context.msg_info.m_hash);
Expand Down
5 changes: 4 additions & 1 deletion src/handler/sign_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ int handler_sign_tx(buffer_t *cdata, uint8_t chunk, bool more) {
(size_t) G_context.bip32_path_len)) {
return io_send_sw(SW_WRONG_DATA_LENGTH);
}
if (!is_valid_bip44_prefix(G_context.bip32_path, G_context.bip32_path_len)) {
return io_send_sw(SW_INVALID_PATH);
}
return io_send_sw(SW_OK);

} else { // parse transaction
Expand Down Expand Up @@ -96,7 +99,7 @@ static int handler_hash_tx_and_display_tx(bool is_blind_signing) {

explicit_bzero(&second_hash, sizeof(second_hash));
if (!res) {
return io_send_sw(SW_TX_HASH_FAIL);
return io_send_sw(SW_HASH_FAIL);
} else {
G_context.state = STATE_PARSED;
return ui_display_transaction(is_blind_signing);
Expand Down
12 changes: 6 additions & 6 deletions src/sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@
*/
#define SW_TX_PARSING_FAIL 0xB005
/**
* Status word for fail of transaction hash.
* Status word for fail of hash.
*/
#define SW_TX_HASH_FAIL 0xB006
#define SW_HASH_FAIL 0xB006
/**
* Status word for bad state.
*/
Expand All @@ -65,10 +65,10 @@
*/
#define SW_PERSONAL_MSG_PARSING_FAIL 0xB009
/**
* Status word for wrong personal msg length.
* Status word for invalid transaction.
*/
#define SW_WRONG_PERSONAL_MSG_LENGTH 0xB00A
#define SW_INVALID_TRANSACTION 0xB00A
/**
* Status word for invalid transaction.
* Status word for invalid path.
*/
#define SW_INVALID_TRANSACTION 0xB00B
#define SW_INVALID_PATH 0xB00B
12 changes: 12 additions & 0 deletions src/transaction/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
#define P64_R 6 // 2^64 % 10
#define P64_Q 1844674407370955161ULL // 2^64 / 10

#define BIP44_COIN_TYPE_1024 0x80000400 // 1024' (hardened)
#define BIP44_COIN_TYPE_888 0x80000378 // 888' (hardened)
#define BIP44_PURPOSE 0x8000002C // 44' (hardened)
static bool convert_bytes_to_uint64_le(const uint8_t *amount, const size_t len, uint64_t *out) {
if (amount == NULL || out == NULL) {
return false;
Expand Down Expand Up @@ -228,3 +231,12 @@ bool convert_param_amount_to_chars(tx_parameter_t *param,
convert_params_to_uint128_le(param, has_prefix, &low, &high) &&
format_fpu128_trimmed(amount, amount_len, low, high, decimals);
}

bool is_valid_bip44_prefix(uint32_t *path, uint8_t path_len) {
if (path_len < 2) { // Need at least purpose and coin type
return false;
}
// Check for 44' (purpose) followed by 1024' or 888' (coin type)
return path[0] == BIP44_PURPOSE &&
(path[1] == BIP44_COIN_TYPE_1024 || path[1] == BIP44_COIN_TYPE_888);
}
14 changes: 13 additions & 1 deletion src/transaction/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,16 @@ bool convert_param_amount_to_chars(tx_parameter_t *param,
*/
static inline bool methodcmp(const tx_parameter_t *param, const char *method_name) {
return param->len == strlen(method_name) && memcmp(param->data, method_name, param->len) == 0;
}
}

/**
* Validate a BIP-32 path prefix (44'/1024' or 44'/888').
*
* @param[in] path
* Pointer to the array representing the BIP-32 path.
* @param[in] path_len
* Length of the path array.
*
* @return true if the path has a valid BIP-44 prefix, false otherwise.
*/
bool is_valid_bip44_prefix(uint32_t *path, uint8_t path_len);
6 changes: 3 additions & 3 deletions tests/application_client/boilerplate_command_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ class Errors(IntEnum):
SW_DISPLAY_AMOUNT_FAIL = 0xB003
SW_WRONG_TX_LENGTH = 0xB004
SW_TX_PARSING_FAIL = 0xB005
SW_TX_HASH_FAIL = 0xB006
SW_HASH_FAIL = 0xB006
SW_BAD_STATE = 0xB007
SW_SIGNATURE_FAIL = 0xB008
SW_PERSONAL_MSG_PARSING_FAIL = 0xB009
SW_WRONG_PERSONAL_MSG_LENGTH = 0xB00A
SW_INVALID_TRANSACTION = 0xB00B
SW_INVALID_TRANSACTION = 0xB00A
SW_INVALID_PATH = 0xB00B


def split_message(message: bytes, max_size: int) -> List[bytes]:
Expand Down
Loading