Skip to content

Commit

Permalink
check and sign wip
Browse files Browse the repository at this point in the history
  • Loading branch information
IdaTucker committed Jul 14, 2023
1 parent 5e6379a commit fbb31b9
Show file tree
Hide file tree
Showing 9 changed files with 394 additions and 2 deletions.
135 changes: 135 additions & 0 deletions app/src/apdu_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,128 @@ __Z_INLINE void handleExtractOutputDataMASPTransfer(volatile uint32_t *tx, uint3
}
}

__Z_INLINE void handleCheckandSignMASPTransfer(volatile uint32_t *tx, uint32_t rx) {
if (!process_chunk(tx, rx)) {
THROW(APDU_CODE_OK);
}
*tx = 0;

zemu_log("----[handleCheckandSignMASPTransfer]\n");

const uint8_t *message = tx_get_buffer();
const uint16_t messageLength = tx_get_buffer_length();

const uint8_t txVersion = G_io_apdu_buffer[OFFSET_P2];

char buffer[20];
zemu_log_stack(buffer);

if (get_state() != STATE_PROCESSED_ALL_EXTRACTIONS) {
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_CODE_UNPROCESSED_TX);
}

set_state(STATE_CHECKING_ALL_TXDATA);
view_tx_state();

zxerr_t err = crypto_check_prevouts(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message);
if (err != zxerr_ok) {
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_CODE_PREVOUT_INVALID);
}

err = crypto_check_sequence(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message);
if (err != zxerr_ok) {
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_CODE_SEQUENCE_INVALID);
}

err = crypto_check_outputs(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength);
if (err != zxerr_ok) {
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_CODE_OUTPUTS_INVALID);
}

// For NU5 there are no joinsplits to check

// /!\ the valuebalance is different to the total value
// TODO in MASP there is a valuebalance per asset type. We need to check each one (?)
err = crypto_check_valuebalance(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, txVersion);
if(err != zxerr_ok){
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_CODE_BAD_VALUEBALANCE);
}

err = crypto_checkspend_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength, txVersion);
if (err != zxerr_ok) {
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_CODE_SPEND_INVALID);
}

err = crypto_checkoutput_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength, txVersion);
if (err != zxerr_ok) {
zemu_log("----[crypto_checkoutput_sapling failed]\n");
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_CODE_OUTPUT_CONTENT_INVALID);
}

err = crypto_checkencryptions_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message);
if (err != zxerr_ok) {
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_CODE_ENCRYPTION_INVALID);
}

set_state(STATE_VERIFIED_ALL_TXDATA);
view_tx_state();

err = crypto_sign_and_check_transparent(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength, txVersion);
if (err != zxerr_ok) {
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_CODE_CHECK_SIGN_TR_FAIL);
}

err = crypto_signspends_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength, txVersion);
if (err != zxerr_ok) {
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_SIGN_SPEND_FAIL);
}

err = crypto_hash_messagebuffer(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength);
if (err != zxerr_ok) {
MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
view_idle_show(0, NULL);
transaction_reset();
THROW(APDU_CODE_HASH_MSG_BUF_FAIL);
}

set_state(STATE_SIGNED_TX);
view_tx_state();

*tx = 32;
THROW(APDU_CODE_OK);
}


// Get the sapling full viewing key fvk = (ak, nk, ovk, dk)
__Z_INLINE void handleGetKeyFVK(volatile uint32_t *flags,
volatile uint32_t *tx, uint32_t rx) {
Expand Down Expand Up @@ -392,6 +514,19 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
break;
}

// Step 4 in signing a MASP transaction:
// The client has already received all the information required
// to build shielded inputs (spends) and outputs. In this APDU call
// the client sends this transaction to the ledger. The ledger
// compares the received txn to what it had received and displayed
// in INS_INIT_MASP_TRANSFER, and, if everything is ok, it will
// sign each transarent input and each spend (shielded input).
// The signatures are stored in flash (not returned to the client yet).
case INS_CHECKANDSIGN: {
CHECK_PIN_VALIDATED()
handleCheckandSignMASPTransfer(tx, rx);
break;
}

#if defined(APP_TESTING)
case INS_TEST: {
Expand Down
4 changes: 4 additions & 0 deletions app/src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
#define SPEND_LIST_SIZE 5
#define OUTPUT_LIST_SIZE 5

#define PREVOUT_SIZE 36
#define T_OUTPUT_SIZE 34 // script size (26) + value size (uint64_t -> 8)


#define ZIP32_SEED_SIZE 64

#define ED25519_SK_SIZE 64
Expand Down
74 changes: 73 additions & 1 deletion app/src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "zxmacros.h"
#include "zxformat.h"
#include "tx.h"
#include "txid.h"

#include "cx.h"
#include "cx_sha256.h"
Expand Down Expand Up @@ -571,6 +572,8 @@ zxerr_t crypto_extracttx_sapling(uint8_t *buffer, uint16_t bufferLen, const uint
pars_ctx.buffer = start + INDEX_INPUT_INPUTVALUE;
pars_ctx.bufferLen = 8;
uint64_t v = 0;
// TODO: Here when we read the value it should be parametrized by the asset type
// so we should also read the asset identifier and store this
pars_err = _readUInt64(&pars_ctx, &v);
if (pars_err != parser_ok) {
return (zxerr_t) EXTRACT_SAPLING_E8;
Expand All @@ -583,6 +586,7 @@ zxerr_t crypto_extracttx_sapling(uint8_t *buffer, uint16_t bufferLen, const uint
random_fr(rnd1);
random_fr(rnd2);

// This needs to be parametrised by the asset type (of v)
zxerr_t err = spendlist_append_item(p, v, div, pkd, rnd1, rnd2);
if (err != zxerr_ok) {
return (zxerr_t) EXTRACT_SAPLING_E9;
Expand Down Expand Up @@ -750,4 +754,72 @@ zxerr_t crypto_extract_output_rnd(uint8_t *buffer, uint16_t bufferLen, uint16_t
set_state(STATE_PROCESSED_ALL_EXTRACTIONS);
}
return zxerr_ok;
}
}

// handleCheckandSignMASPTransfer step 1/11
zxerr_t crypto_check_prevouts(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata){
zemu_log_stack("crypto_check_prevouts");
MEMZERO(buffer, bufferLen);

if(get_state() != STATE_CHECKING_ALL_TXDATA){
return zxerr_unknown;
}

uint8_t hash[HASH_LEN] = {0};
size_t prevouts_hash_offset = 0;
nu5_transparent_prevouts_hash(txdata,hash);
prevouts_hash_offset = NU5_INDEX_HASH_PREVOUTSHASH;

if(MEMCMP(hash, txdata + start_sighashdata() + prevouts_hash_offset, HASH_LEN) != 0){
return zxerr_unknown;
}
return zxerr_ok;
}

// handleCheckandSign step 2/11
zxerr_t crypto_check_sequence(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata){
zemu_log_stack("crypto_check_sequence");
MEMZERO(buffer, bufferLen);

if(get_state() != STATE_CHECKING_ALL_TXDATA){
return zxerr_unknown;
}

uint8_t hash[HASH_LEN] = {0};
size_t sequence_hash_offset = 0;

nu5_transparent_sequence_hash(txdata,hash);
sequence_hash_offset = NU5_INDEX_HASH_SEQUENCEHASH;

if(MEMCMP(hash, txdata + start_sighashdata() + sequence_hash_offset, HASH_LEN) != 0){
return zxerr_unknown;
}
return zxerr_ok;
}

// handleCheckandSign step 3/11
zxerr_t crypto_check_outputs(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen){
zemu_log_stack("crypto_check_outputs");
if(start_sighashdata() + SAPLING_LENGTH_HASH_DATA != txdatalen){
return zxerr_unknown;
}

if(get_state() != STATE_CHECKING_ALL_TXDATA){
return zxerr_unknown;
}

MEMZERO(buffer, bufferLen);
uint8_t hash[HASH_LEN] = {0};
size_t sapling_outputs_hash_offset = 0;


nu5_transparent_outputs_hash(hash);
sapling_outputs_hash_offset = NU5_INDEX_HASH_OUTPUTSHASH;


if(MEMCMP(hash, txdata + start_sighashdata() + sapling_outputs_hash_offset, HASH_LEN) != 0){
return zxerr_unknown;
}
return zxerr_ok;
}

6 changes: 6 additions & 0 deletions app/src/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ zxerr_t crypto_extracttx_sapling(uint8_t *buffer, uint16_t bufferLen, const uint
zxerr_t crypto_hash_messagebuffer(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, uint16_t txdataLen);
zxerr_t crypto_extract_spend_proof_key_and_rnd(uint8_t *buffer, uint16_t bufferLen);
zxerr_t crypto_extract_output_rnd(uint8_t *buffer, uint16_t bufferLen, uint16_t *replyLen);

// Functions called for check and sign of masp transfers
zxerr_t crypto_check_prevouts(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata);
zxerr_t crypto_check_sequence(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata);
zxerr_t crypto_check_outputs(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen);

#ifdef __cplusplus
}
#endif
6 changes: 5 additions & 1 deletion app/src/index_sapling.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,18 @@
#define INDEX_OUTPUT_OUT 676

#define SAPLING_LENGTH_HASH_DATA 220
#define SAPLING_INDEX_HASH_PREVOUTSHASH 8
#define SAPLING_INDEX_HASH_SEQUENCEHASH 40
#define SAPLING_INDEX_HASH_OUTPUTSHASH 72
#define SAPLING_INDEX_HASH_JOINSPLITSHASH 104
#define SAPLING_INDEX_HASH_SHIELDEDSPENDHASH 136
#define SAPLING_INDEX_HASH_SHIELDEDOUTPUTHASH 168
#define SAPLING_INDEX_HASH_VALUEBALANCE 208

#define NU5_INDEX_HASH_PREVOUTSHASH 20 // 32 bytes
#define NU5_INDEX_HASH_SEQUENCEHASH 52 // 32 bytes
#define NU5_INDEX_HASH_OUTPUTSHASH 84 // 32 bytes


uint16_t length_t_in_data();

uint16_t length_spend_old_data();
Expand Down
4 changes: 4 additions & 0 deletions app/src/nvdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ t_output_item_t *t_outlist_retrieve_item(uint8_t i) {
}
}

uint8_t t_outlist_len() {
return transaction_header.t_out_len;
}

zxerr_t transparent_signatures_append(uint8_t *signature) {
if (transaction_header.t_sign_index >= transaction_header.t_in_len) {
return zxerr_unknown;
Expand Down
5 changes: 5 additions & 0 deletions app/src/nvdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ typedef struct {

typedef struct {
uint64_t total_value;
// TODO: sapling_value should be parametrized by asset type
// so there should be a list of pairs (value, asset_type)
int64_t sapling_value;
uint8_t state;
uint8_t t_in_len;
Expand Down Expand Up @@ -117,6 +119,8 @@ uint8_t t_inlist_len();

//transparent TXOUT API
zxerr_t t_outlist_append_item(uint8_t *addr, uint64_t v);
t_output_item_t *t_outlist_retrieve_item(uint8_t i);
uint8_t t_outlist_len();

// spend list nvdata functions
zxerr_t spendlist_append_item(uint32_t p, uint64_t v, uint8_t *div, uint8_t *pkd, uint8_t *rcm, uint8_t *alpha);
Expand All @@ -137,6 +141,7 @@ zxerr_t transparent_signatures_append(uint8_t *signature);
zxerr_t spend_signatures_append(uint8_t *signature);


// TODO valuebalance should be per asset type
//metadata flash api
int64_t get_valuebalance();

Expand Down
Loading

0 comments on commit fbb31b9

Please sign in to comment.