Skip to content

Commit

Permalink
Merge pull request #141 from Zondax/combined_tx
Browse files Browse the repository at this point in the history
Combined request + state read
  • Loading branch information
jleni authored Dec 20, 2021
2 parents c65a532 + 4444dda commit 5edf84e
Show file tree
Hide file tree
Showing 44 changed files with 466 additions and 20 deletions.
4 changes: 2 additions & 2 deletions app/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ ifndef COIN
COIN=ICP
endif

APPVERSION_M=1
APPVERSION_N=2
APPVERSION_M=2
APPVERSION_N=0
APPVERSION_P=0

$(info COIN = [$(COIN)])
Expand Down
31 changes: 31 additions & 0 deletions app/src/apdu_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,29 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint
*flags |= IO_ASYNCH_REPLY;
}

__Z_INLINE void handleSignCombined(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
if (!process_chunk(tx, rx)) {
THROW(APDU_CODE_OK);
}

CHECK_APP_CANARY()

const char *error_msg = tx_parse_combined();
CHECK_APP_CANARY()

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);
}

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

void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
uint16_t sw = 0;

Expand Down Expand Up @@ -112,6 +135,14 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
break;
}

case INS_SIGN_COMBINED: {
if (os_global_pin_is_validated() != BOLOS_UX_OK) {
THROW(APDU_CODE_COMMAND_NOT_ALLOWED);
}
handleSignCombined(flags, tx, rx);
break;
}

default:
THROW(APDU_CODE_INS_NOT_SUPPORTED);
}
Expand Down
14 changes: 14 additions & 0 deletions app/src/common/actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ __Z_INLINE void app_sign() {
}
}

__Z_INLINE void app_sign_combined() {
uint16_t replyLen = 0;

zxerr_t err = crypto_sign_combined(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3,&G_io_apdu_buffer[0], &G_io_apdu_buffer[32], &replyLen);

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 zxerr_t app_fill_address() {
// Put data directly in the apdu buffer
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
Expand Down
6 changes: 4 additions & 2 deletions app/src/common/app_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ bool process_chunk(volatile uint32_t *tx, uint32_t rx) {
THROW(APDU_CODE_DATA_INVALID);
}

bool is_stake_tx = parser_tx_obj.tx_fields.call.special_transfer_type == neuron_stake_transaction;
bool is_stake_tx = parser_tx_obj.special_transfer_type == neuron_stake_transaction;

uint32_t added;
switch (payloadType) {
Expand All @@ -146,7 +146,9 @@ bool process_chunk(volatile uint32_t *tx, uint32_t rx) {
extractHDPath(rx, OFFSET_DATA);
MEMZERO(&parser_tx_obj, sizeof(parser_tx_t));
if(G_io_apdu_buffer[OFFSET_P2] == 1){
parser_tx_obj.tx_fields.call.special_transfer_type = neuron_stake_transaction;
parser_tx_obj.special_transfer_type = neuron_stake_transaction;
}else{
parser_tx_obj.special_transfer_type = normal_transaction;
}
tx_initialized = true;
return false;
Expand Down
1 change: 1 addition & 0 deletions app/src/common/app_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#define INS_GET_VERSION 0x00
#define INS_GET_ADDR 0x01
#define INS_SIGN 0x02
#define INS_SIGN_COMBINED 0x03

void app_init();

Expand Down
3 changes: 3 additions & 0 deletions app/src/common/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ const char *parser_getErrorDescription(parser_error_t err);
//// parses a tx buffer
parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t dataLen);

/// parses a tx buffer of a combined transaction
parser_error_t parser_parse_combined(parser_context_t *ctx, const uint8_t *data, size_t dataLen);

//// verifies tx fields
parser_error_t parser_validate(const parser_context_t *ctx);

Expand Down
20 changes: 20 additions & 0 deletions app/src/common/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,26 @@ const char *tx_parse() {
return NULL;
}

const char *tx_parse_combined() {
uint8_t err = parser_parse_combined(
&ctx_parsed_tx,
tx_get_buffer(),
tx_get_buffer_length());

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

err = parser_validate(&ctx_parsed_tx);
CHECK_APP_CANARY()

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

return NULL;
}

zxerr_t tx_getNumItems(uint8_t *num_items) {
parser_error_t err = parser_getNumItems(&ctx_parsed_tx, num_items);

Expand Down
3 changes: 3 additions & 0 deletions app/src/common/tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ uint8_t *tx_get_buffer();
/// \return It returns NULL if data is valid or error message otherwise.
const char *tx_parse();

///Parses combined transaction message in transaction buffer
const char *tx_parse_combined();

/// Return the number of items in the transaction
zxerr_t tx_getNumItems(uint8_t *num_items);

Expand Down
119 changes: 119 additions & 0 deletions app/src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ uint8_t const DER_PREFIX[] = {0x30, 0x56, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x
#define STAKEACCOUNT_PREFIX_SIZE 12u
#define STAKEACCOUNT_PRINCIPAL_SIZE 10u

#define SIGNATURE_SIZE_R 32
#define SIGNATURE_SIZE_S 32
#define SIGNATURE_SIZE_RS 64

#if defined(TARGET_NANOS) || defined(TARGET_NANOX)
#include "cx.h"

Expand Down Expand Up @@ -262,12 +266,127 @@ zxerr_t crypto_sign(uint8_t *signatureBuffer,
return err;
}

//Start:
//PREDIGEST_REQUEST || PREDIGEST_STATEREAD
//END:
//DIGEST_REQUEST || SIGNATURE_REQUEST || DIGEST_STATEREAD || SIGNATURE_STATEREAD

zxerr_t crypto_sign_combined(uint8_t *signatureBuffer,
uint16_t signatureMaxlen,
uint8_t *predigest_request,
uint8_t *predigest_stateread,
uint16_t *sigSize) {
if (signatureMaxlen < 2*(CX_SHA256_SIZE + SIGNATURE_SIZE_RS)){
return zxerr_buffer_too_small;
}

uint8_t message_buffer[SIGN_PREFIX_SIZE + CX_SHA256_SIZE];
MEMZERO(message_buffer, sizeof(message_buffer));

uint8_t message_digest[CX_SHA256_SIZE];
MEMZERO(message_digest,sizeof(message_digest));

message_buffer[0] = 0x0a;
MEMCPY(&message_buffer[1], (uint8_t *)"ic-request",SIGN_PREFIX_SIZE - 1);

MEMCPY(message_buffer + SIGN_PREFIX_SIZE, predigest_stateread, CX_SHA256_SIZE);

CHECK_APP_CANARY()

cx_hash_sha256(message_buffer, SIGN_PREHASH_SIZE, message_digest, CX_SHA256_SIZE);
MEMCPY(signatureBuffer + CX_SHA256_SIZE + SIGNATURE_SIZE_RS, message_digest, CX_SHA256_SIZE);


MEMCPY(message_buffer + SIGN_PREFIX_SIZE, predigest_request, CX_SHA256_SIZE);
cx_hash_sha256(message_buffer, SIGN_PREHASH_SIZE, message_digest, CX_SHA256_SIZE);
MEMCPY(signatureBuffer, message_digest, CX_SHA256_SIZE);

CHECK_APP_CANARY()

cx_ecfp_private_key_t cx_privateKey;
uint8_t privateKeyData[32];
unsigned int info = 0;
int signatureLength = 0;

signature_t sigma;
MEMZERO(&sigma, sizeof(signature_t));

zxerr_t err = zxerr_ok;
BEGIN_TRY
{
TRY
{
// Generate keys
os_perso_derive_node_bip32(CX_CURVE_SECP256K1,
hdPath,
HDPATH_LEN_DEFAULT,
privateKeyData, NULL);

cx_ecfp_init_private_key(CX_CURVE_SECP256K1, privateKeyData, 32, &cx_privateKey);

// Sign request
signatureLength = cx_ecdsa_sign(&cx_privateKey,
CX_RND_RFC6979 | CX_LAST,
CX_SHA256,
signatureBuffer,
CX_SHA256_SIZE,
sigma.der_signature,
sizeof_field(signature_t, der_signature),
&info);

err_convert_e err_c = convertDERtoRSV(sigma.der_signature, info, sigma.r, sigma.s, &sigma.v);
if (err_c != no_error) {
MEMZERO(signatureBuffer, signatureMaxlen);
err = zxerr_unknown;
}else{
MEMCPY(signatureBuffer + CX_SHA256_SIZE, sigma.r, SIGNATURE_SIZE_R);
MEMCPY(signatureBuffer + CX_SHA256_SIZE + SIGNATURE_SIZE_R, sigma.s, SIGNATURE_SIZE_S);

MEMZERO(&sigma, sizeof(signature_t));
// Sign stateread
signatureLength = cx_ecdsa_sign(&cx_privateKey,
CX_RND_RFC6979 | CX_LAST,
CX_SHA256,
signatureBuffer + CX_SHA256_SIZE + SIGNATURE_SIZE_RS,
CX_SHA256_SIZE,
sigma.der_signature,
sizeof_field(signature_t, der_signature),
&info);

err_convert_e err_c = convertDERtoRSV(sigma.der_signature, info, sigma.r, sigma.s, &sigma.v);
if (err_c != no_error) {
MEMZERO(signatureBuffer, signatureMaxlen);
err = zxerr_unknown;
}else{
MEMCPY(signatureBuffer + 2*CX_SHA256_SIZE + SIGNATURE_SIZE_RS, sigma.r, SIGNATURE_SIZE_R);
MEMCPY(signatureBuffer + 2*CX_SHA256_SIZE + SIGNATURE_SIZE_RS + SIGNATURE_SIZE_R, sigma.s, SIGNATURE_SIZE_S);
*sigSize = 2*(CX_SHA256_SIZE + SIGNATURE_SIZE_RS);
}
}
}
CATCH_ALL {
err = zxerr_ledger_api_error;
}
FINALLY {
MEMZERO(&cx_privateKey, sizeof(cx_privateKey));
MEMZERO(privateKeyData, 32);
}
}
END_TRY;

return err;
}


#else

#include <hexutils.h>
#include "picohash.h"

zxerr_t crypto_getDigest(uint8_t *digest, txtype_e txtype){
return zxerr_ok;
}

zxerr_t cx_hash_sha256(uint8_t *input, uint16_t inputLen, uint8_t *output, uint16_t outputLen) {
if (outputLen < 32) {
return zxerr_invalid_crypto_settings;
Expand Down
10 changes: 10 additions & 0 deletions app/src/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ extern "C" {
#include <sigutils.h>
#include <zxerror.h>

#include "parser_txdef.h"

extern uint32_t hdPath[HDPATH_LEN_DEFAULT];

bool isTestnet();
Expand Down Expand Up @@ -54,6 +56,14 @@ zxerr_t crypto_sign(uint8_t *signature,
uint16_t signatureMaxlen,
uint16_t *sigSize);

zxerr_t crypto_sign_combined(uint8_t *signatureBuffer,
uint16_t signatureMaxlen,
uint8_t *predigest_request,
uint8_t *predigest_stateread,
uint16_t *sigSize);

zxerr_t crypto_getDigest(uint8_t *digest, txtype_e txtype);

zxerr_t crypto_principalToStakeAccount(const uint8_t *principal, uint16_t principalLen,
const uint64_t neuron_creation_memo,
uint8_t *address, uint16_t maxoutLen);
Expand Down
Loading

0 comments on commit 5edf84e

Please sign in to comment.