Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nft transactions #107

Open
wants to merge 4 commits into
base: message_signing
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ file(GLOB_RECURSE LIB_SRC
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/json/json_parser.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/tx_metadata.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/script_parser.c
app/src/base32.c
app/src/crypto.c
)
Expand Down
87 changes: 47 additions & 40 deletions app/src/apdu_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "hdpath.h"
#include "parser_impl.h"
#include "message.h"
#include "script_parser.h"

__Z_INLINE void handleGetPubkey(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
hasPubkey = false;
Expand Down Expand Up @@ -83,50 +84,56 @@ __Z_INLINE void handleGetPubkey(volatile uint32_t *flags, volatile uint32_t *tx,

__Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
process_chunk_response_t callType = process_chunk(tx, rx);
if (callType == PROCESS_CHUNK_NOT_FINISHED) {
THROW(APDU_CODE_OK);
}

if (callType == PROCESS_CHUNK_FINISHED_MESSAGE) {
zxerr_t err = message_parse();
if (err != zxerr_ok) {
const char *error_msg = "Invalid message";
int error_msg_length = strlen(error_msg);
MEMCPY(G_io_apdu_buffer, error_msg, error_msg_length);
*tx += (error_msg_length);
THROW(APDU_CODE_DATA_INVALID);
}
CHECK_APP_CANARY()
view_review_init(message_getItem, message_getNumItems, app_sign_message);
view_review_show();
*flags |= IO_ASYNCH_REPLY;
}

const char *error_msg = tx_parse(callType);

if (error_msg != NULL) {
int error_msg_length = strlen(error_msg);
MEMCPY(G_io_apdu_buffer, error_msg, error_msg_length);
*tx += (error_msg_length);
THROW(APDU_CODE_DATA_INVALID);
}
switch (callType) {
case PROCESS_CHUNK_NOT_FINISHED:
THROW(APDU_CODE_OK);
case PROCESS_CHUNK_FINISHED_MESSAGE:;
zxerr_t err = message_parse();
if (err != zxerr_ok) {
const char *error_msg = "Invalid message";
int error_msg_length = strlen(error_msg);
MEMCPY(G_io_apdu_buffer, error_msg, error_msg_length);
*tx += (error_msg_length);
THROW(APDU_CODE_DATA_INVALID);
}
CHECK_APP_CANARY()
view_review_init(message_getItem, message_getNumItems, app_sign_message);
view_review_show();
*flags |= IO_ASYNCH_REPLY;
break;
case PROCESS_CHUNK_FINISHED_NFT1:
case PROCESS_CHUNK_FINISHED_NFT2:
case PROCESS_CHUNK_FINISHED_NO_METADATA:
case PROCESS_CHUNK_FINISHED_WITH_METADATA: ;
const char *error_msg = tx_parse(callType);

if (error_msg != NULL) {
int error_msg_length = strlen(error_msg);
MEMCPY(G_io_apdu_buffer, error_msg, error_msg_length);
*tx += (error_msg_length);
THROW(APDU_CODE_DATA_INVALID);
}

show_address = SHOW_ADDRESS_NONE;
loadAddressCompareHdPathFromSlot();

//if we found matching hdPath on slot 0
if (show_address == SHOW_ADDRESS_YES || show_address == SHOW_ADDRESS_YES_HASH_MISMATCH) {
checkAddressUsedInTx();
}
else {
addressUsedInTx = 0;
}

show_address = SHOW_ADDRESS_NONE;
loadAddressCompareHdPathFromSlot();

//if we found matching hdPath on slot 0
if (show_address == SHOW_ADDRESS_YES || show_address == SHOW_ADDRESS_YES_HASH_MISMATCH) {
checkAddressUsedInTx();
CHECK_APP_CANARY()
view_review_init(tx_getItem, tx_getNumItems, app_sign);
view_review_show();
*flags |= IO_ASYNCH_REPLY;
break;
default:
THROW(APDU_CODE_UNKNOWN);
}
else {
addressUsedInTx = 0;
}

CHECK_APP_CANARY()
view_review_init(tx_getItem, tx_getNumItems, app_sign);
view_review_show();
*flags |= IO_ASYNCH_REPLY;
}

__Z_INLINE void handleSlotStatus(__Z_UNUSED volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
Expand Down
16 changes: 13 additions & 3 deletions app/src/common/app_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ void extractHDPathAndCryptoOptions(uint32_t rx, uint32_t offset) {

process_chunk_response_t process_chunk(__Z_UNUSED volatile uint32_t *tx, uint32_t rx) {
const uint8_t payloadType = G_io_apdu_buffer[OFFSET_PAYLOAD_TYPE];
const uint8_t p2 = G_io_apdu_buffer[OFFSET_P2];

if (G_io_apdu_buffer[OFFSET_P2] != 0) {
if (p2 != 0 && payloadType != 0x02) {
THROW(APDU_CODE_INVALIDP1P2);
}

Expand All @@ -127,7 +128,7 @@ process_chunk_response_t process_chunk(__Z_UNUSED volatile uint32_t *tx, uint32_

uint32_t added;
switch (payloadType) {
case 0:
case 0x00:
tx_initialize();
tx_reset();
extractHDPathAndCryptoOptions(rx, OFFSET_DATA);
Expand All @@ -144,7 +145,16 @@ process_chunk_response_t process_chunk(__Z_UNUSED volatile uint32_t *tx, uint32_
if (added != rx - OFFSET_DATA) {
THROW(APDU_CODE_OUTPUT_BUFFER_TOO_SMALL);
}
return PROCESS_CHUNK_FINISHED_NO_METADATA;
switch (p2) {
case 0x01:
return PROCESS_CHUNK_FINISHED_NO_METADATA;
case 0x02:
return PROCESS_CHUNK_FINISHED_NFT1;
case 0x03:
return PROCESS_CHUNK_FINISHED_NFT2;
default:
THROW(APDU_CODE_INVALIDP1P2);
}
case 0x03:
if (storeTxMetadata(&(G_io_apdu_buffer[OFFSET_DATA]), rx - OFFSET_DATA) != PARSER_OK) {
initStoredTxMetadata(); //delete merkle tree proof on error for redundant security
Expand Down
2 changes: 2 additions & 0 deletions app/src/common/app_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ typedef enum {
PROCESS_CHUNK_NOT_FINISHED = 0,
PROCESS_CHUNK_FINISHED_WITH_METADATA,
PROCESS_CHUNK_FINISHED_NO_METADATA,
PROCESS_CHUNK_FINISHED_NFT1,
PROCESS_CHUNK_FINISHED_NFT2,
PROCESS_CHUNK_FINISHED_MESSAGE,
} process_chunk_response_t;

Expand Down
37 changes: 23 additions & 14 deletions app/src/common/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,31 +75,40 @@ uint8_t *tx_get_buffer() {
}

const char *tx_parse(process_chunk_response_t typeOfCall) {
script_parsed_type_t scriptType = (typeOfCall == PROCESS_CHUNK_FINISHED_NFT1) ? SCRIPT_TYPE_NFT_SETUP_COLLECTION :
(typeOfCall == PROCESS_CHUNK_FINISHED_NFT2) ? SCRIPT_TYPE_NFT_TRANSFER : SCRIPT_TYPE_UNKNOWN;
// parse tx
uint8_t err = parser_parse(
&ctx_parsed_tx,
tx_get_buffer(),
tx_get_buffer_length());
tx_get_buffer_length(),
scriptType);

if (err != PARSER_OK) {
return parser_getErrorDescription(err);
}

//parse metadata
parser_tx_obj.metadataInitialized = false;
if (typeOfCall == PROCESS_CHUNK_FINISHED_WITH_METADATA) {
MEMZERO(&parser_tx_obj.metadata, sizeof(parser_tx_obj.metadata));
err = parseTxMetadata(parser_tx_obj.hash.digest, &parser_tx_obj.metadata);
if (err != PARSER_OK) {
return parser_getErrorDescription(err);
}
parser_tx_obj.metadataInitialized = true;
}
else {
//If no metadata provided = script is not known, expert mode must be on
if (!app_mode_expert()) {
return parser_getErrorDescription(PARSER_UNEXPECTED_SCRIPT);
}
switch (typeOfCall) {
case PROCESS_CHUNK_FINISHED_WITH_METADATA:
MEMZERO(&parser_tx_obj.metadata, sizeof(parser_tx_obj.metadata));
err = parseTxMetadata(parser_tx_obj.hash.digest, &parser_tx_obj.metadata);
if (err != PARSER_OK) {
return parser_getErrorDescription(err);
}
parser_tx_obj.metadataInitialized = true;
break;
case PROCESS_CHUNK_FINISHED_NFT1:
case PROCESS_CHUNK_FINISHED_NFT2:
break; // we do not need metadata for these scripts
case PROCESS_CHUNK_FINISHED_NO_METADATA:
if (!app_mode_expert()) { // we do not need metadata for these scripts, but this workflow should work only in expert mode
return parser_getErrorDescription(PARSER_UNEXPECTED_SCRIPT);
}
break;
default:
return parser_getErrorDescription(PARSER_UNEXPECTED_ERROR);
}

CHECK_APP_CANARY()
Expand Down
Loading