Skip to content

Commit

Permalink
get spend info apdu.
Browse files Browse the repository at this point in the history
  • Loading branch information
IdaTucker committed Jul 14, 2023
1 parent e76ef5e commit 261bd49
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 9 deletions.
37 changes: 36 additions & 1 deletion app/src/apdu_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,27 @@ __Z_INLINE void handleInitMASPTransfer(volatile uint32_t *flags,

}

__Z_INLINE void handleExtractSpendDataMASPTransfer(volatile uint32_t *tx, uint32_t rx) {
zemu_log("----[handleExtractSpendDataMASPTransfer]\n");

// Get the sapling full viewing key (ak, nk, ovk)
*tx = 0;
if (rx != APDU_MIN_LENGTH || G_io_apdu_buffer[OFFSET_DATA_LEN] != 0) {
THROW(APDU_CODE_COMMAND_NOT_ALLOWED);
}
// TODO implement the following
zxerr_t err = crypto_extract_spend_proof_key_and_rnd(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2);
view_tx_state();
if (err == zxerr_ok) {
*tx = 128; //SPEND_EXTRACT_LEN
THROW(APDU_CODE_OK);
} else {
*tx = 0;
THROW(APDU_CODE_DATA_INVALID);
}

}

// 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) {
zemu_log("----[handleGetKeyFVK]\n");
Expand Down Expand Up @@ -310,20 +329,36 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
}

// MASP transactions
// Get full viewing key fvk = (ak, nk, ovk, dk)
case INS_GET_FVK: {
zemu_log("----[INS_GET_FVK]\n");
CHECK_PIN_VALIDATED()
handleGetKeyFVK(flags, tx, rx);
break;
}

// Step 1 in signing a MASP transaction:
// the ledger receives an initial transaction blob
// and stores relevant information in flash memory,
// so that it can check consistency with what it signs later.
case INS_INIT_MASP_TRANSFER: {
zemu_log("----[INS_INIT_MASP_TRANSFER]\n");
CHECK_PIN_VALIDATED()
handleInitMASPTransfer(flags, tx, rx);
break;
}

// If there are any spends (= shielded inputs) this is
// Step 2 in signing a MASP transaction:
// the clients requests information to build SpendDescriptions.
// In particular, the ledger should answer with
// a proof generating key (PGK) and randomness (rcv and alpha)
// This APDU is called for each spend.
case INS_EXTRACT_SPEND: {
CHECK_PIN_VALIDATED()
handleExtractSpendDataMASPTransfer(tx, rx);
break;
}
#if defined(APP_TESTING)
case INS_TEST: {
handleTest(flags, tx, rx);
Expand Down
5 changes: 5 additions & 0 deletions app/src/coin.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,15 @@ typedef enum {
#define INS_SIGN_WRAPPER 0x02

#define INS_GET_SHIELDED_ADDRESS 0x10

#define INS_INIT_MASP_TRANSFER 0xe0
#define INS_EXTRACT_SPEND 0xe1


#define INS_GET_IVK 0xf0
#define INS_GET_OVK 0xf1
#define INS_GET_NF 0xf2
#define INS_GET_FVK 0xf3

#define INS_GET_SIGNATURE 0x0A

Expand Down
65 changes: 64 additions & 1 deletion app/src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ zxerr_t crypto_fillSaplingSeed(uint8_t *sk) {
}


// handleGetKeyFVK: return the full viewing key for a given path
// handleGetKeyFVK: return the full viewing key (fvk = (ak, nk, ovk, dk)) for a given path
zxerr_t crypto_fvk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint16_t *replyLen) {

zemu_log_stack("crypto_fvk_sapling");
Expand Down Expand Up @@ -648,5 +648,68 @@ zxerr_t crypto_hash_messagebuffer(uint8_t *buffer, uint16_t bufferLen, const uin
return zxerr_unknown;
}
cx_hash_sha256(txdata, txdataLen, buffer, CX_SHA256_SIZE); // SHA256
return zxerr_ok;
}

typedef struct {
union {
// STEP 1
struct {
uint8_t zip32_seed[ZIP32_SEED_SIZE];
uint8_t sk[ED25519_SK_SIZE];
} step1;

struct {
uint8_t ask[ASK_SIZE];
uint8_t nsk[NSK_SIZE];
} step2;
};
} tmp_spendinfo_s;

// handleExtractSpendDataMASPTransfer
zxerr_t crypto_extract_spend_proof_key_and_rnd(uint8_t *buffer, uint16_t bufferLen){
// First check that there a still items on the list of spends
// for which spend data has not yet been extracted
if(!spendlist_more_to_extract()){
return zxerr_unknown;
}

// Ensure that the INS_INIT_MASP_TRANSFER has been called
// and did not error.
if(get_state() != STATE_PROCESSED_INPUTS){
return zxerr_unknown;
}

uint8_t *out = (uint8_t *) buffer;
MEMZERO(out, bufferLen);

// Get the next item from the list of spends
const spend_item_t *next = spendlist_extract_next();
if (next == NULL){
return zxerr_unknown;
}

tmp_spendinfo_s tmp = {0};

zxerr_t error = crypto_fillSaplingSeed(tmp.step1.zip32_seed);
CHECK_APP_CANARY()
if(error != zxerr_ok){
MEMZERO(buffer, bufferLen);
return error;
}

// Get ak and nsk (the child proof key)
get_child_proof_key(tmp.step1.zip32_seed, next->path, out, out + AK_SIZE);
CHECK_APP_CANARY()

MEMZERO(&tmp, sizeof(tmp_spendinfo_s));

MEMCPY(out+AK_SIZE+NSK_SIZE, next->rcmvalue, RCM_SIZE);
MEMCPY(out+AK_SIZE+NSK_SIZE+RCM_SIZE, next->alpha,ALPHA_SIZE);

if(!spendlist_more_to_extract()){
set_state(STATE_PROCESSED_SPEND_EXTRACTIONS);
}

return zxerr_ok;
}
1 change: 1 addition & 0 deletions app/src/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ zxerr_t crypto_getSignature(uint8_t *output, uint16_t outputLen, uint8_t slot);
zxerr_t crypto_fvk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint16_t *replyLen);
zxerr_t crypto_extracttx_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen);
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);

#ifdef __cplusplus
}
Expand Down
22 changes: 22 additions & 0 deletions app/src/nvdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,28 @@ uint8_t spendlist_len() {
return transaction_header.spendlist_len;
}

spend_item_t *spendlist_retrieve_item(uint8_t i) {
if (transaction_header.spendlist_len < i) {
return NULL;
} else {
return (spend_item_t *) &N_spendlist.items[i];
}
}

spend_item_t *spendlist_extract_next() {
if (transaction_header.spendlist_len <= transaction_header.spenddata_extract_index) {
return NULL;
} else {
spend_item_t *result = (spend_item_t *) &N_spendlist.items[transaction_header.spenddata_extract_index];
transaction_header.spenddata_extract_index += 1;
return result;
}
}

uint8_t spendlist_more_to_extract() {
return transaction_header.spendlist_len > transaction_header.spenddata_extract_index;
}

zxerr_t outputlist_append_item(uint8_t *d, uint8_t *pkd, uint64_t v, uint8_t memotype, uint8_t *ovk, uint8_t *rcmv,
uint8_t *rseed) {
if (transaction_header.outputlist_len >= OUTPUT_LIST_SIZE) {
Expand Down
3 changes: 3 additions & 0 deletions app/src/nvdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ zxerr_t t_outlist_append_item(uint8_t *addr, uint64_t v);
// 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);
uint8_t spendlist_len();
spend_item_t *spendlist_retrieve_item(uint8_t i);
spend_item_t *spendlist_extract_next();
uint8_t spendlist_more_to_extract();

// shielded output nvdata functions
zxerr_t outputlist_append_item(uint8_t *d, uint8_t *pkd, uint64_t v, uint8_t memotype, uint8_t *ovk, uint8_t *rcmv,
Expand Down
29 changes: 24 additions & 5 deletions app/src/sapling.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ void derive_dummy_ask_and_nsk(uint8_t *key_in, uint8_t *ask_out, uint8_t *nsk_ou
MEMZERO(buffer, sizeof(buffer));
}

void get_fvk(uint8_t *seed, uint32_t pos, full_viewing_key_t* out){
void get_all_keys(uint8_t *seed, uint32_t pos, all_keys_t* out){
uint32_t path[3] = {FIRSTVALUE, COIN_TYPE, pos};

uint8_t master_spending_key[64] = {0};
Expand Down Expand Up @@ -669,9 +669,9 @@ void get_fvk(uint8_t *seed, uint32_t pos, full_viewing_key_t* out){
little_endian_write_u32((c+(1<<31)), le_i, sizeof (le_i));
uint8_t *start_esk = expandedSpendingKey.ask;
masp_blake2b_expand_vec_three(chain, sizeof (chain),
tmp_const, sizeof (tmp_const),
tmp_const, sizeof (tmp_const),
start_esk, sizeof (expandedSpendingKey),
le_i, sizeof (le_i), tmp);
le_i, sizeof (le_i), tmp);
} else {
full_viewing_key_t fvk;
ask_to_ak(expandedSpendingKey.ask, fvk.ak);
Expand All @@ -688,9 +688,9 @@ void get_fvk(uint8_t *seed, uint32_t pos, full_viewing_key_t* out){
little_endian_write_u32(c, le_i, sizeof (le_i));
uint8_t *start_fvk = fvk.ak;
masp_blake2b_expand_vec_three(chain, sizeof (chain),
tmp_const, sizeof (tmp_const),
tmp_const, sizeof (tmp_const),
start_fvk, sizeof (fvk),
le_i, sizeof (le_i), tmp);
le_i, sizeof (le_i), tmp);
}
memcpy(key, tmp, 32);
memcpy(chain, tmp + 32, 32);
Expand Down Expand Up @@ -764,12 +764,31 @@ void get_fvk(uint8_t *seed, uint32_t pos, full_viewing_key_t* out){
memcpy(expandedSpendingKey.dk, buffer, DK_SIZE);
MEMZERO(buffer, sizeof(buffer));
}
memcpy(out->ask, ask_bytes, ASK_SIZE);
memcpy(out->nsk, nsk_bytes, NSK_SIZE);
ask_to_ak(ask_bytes, out->ak);
nsk_to_nk(nsk_bytes, out->nk);
memcpy(out->ovk, expandedSpendingKey.ovk, OVK_SIZE);
memcpy(out->dk, expandedSpendingKey.dk, DK_SIZE);
}

void get_fvk(uint8_t *seed, uint32_t pos, full_viewing_key_t* out){
all_keys_t *keys = NULL;
get_all_keys(seed,pos,keys);
memcpy(out->ak, keys->ak, AK_SIZE);
memcpy(out->nk, keys->nk, NK_SIZE);
memcpy(out->ovk, keys->ovk, OVK_SIZE);
memcpy(out->dk, keys->dk, DK_SIZE);
}


void get_child_proof_key(uint8_t *seed, uint32_t pos, uint8_t* ak_out, uint8_t* nsk_out){
all_keys_t *keys = NULL;
get_all_keys(seed,pos,keys);
memcpy(ak_out, keys->ak, AK_SIZE);
memcpy(nsk_out, keys->nsk, NSK_SIZE);
}


void get_expanded_spending_key_from_seed(uint8_t *seed, expanded_spending_key_t* out){
uint8_t master_spending_key[64] = {0};
Expand Down
5 changes: 4 additions & 1 deletion app/src/sapling.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ extern "C" {
#include <stdint.h> // uint*_t
#include "sapling_keys.h"

void get_fvk(uint8_t *seed, uint32_t pos, full_viewing_key_t* out);
void get_fvk(uint8_t *seed, uint32_t pos, full_viewing_key_t* out);

// Gets keys required for computing the zk proofs for spend descriptions (ak and nsk)
void get_child_proof_key(uint8_t *seed, uint32_t pos, uint8_t* ak_out, uint8_t* nsk_out);

// Exists but not needed out of sapling.c yet:
// static void get_expanded_spending_key_from_seed(uint8_t *seed, expanded_spending_key_t* out);
Expand Down
11 changes: 10 additions & 1 deletion app/src/sapling_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,13 @@ typedef struct {
uint8_t nk[NK_SIZE]; // nullifier deriving key
uint8_t ovk[OVK_SIZE]; // outgoing viewing key
uint8_t dk[DK_SIZE]; // diversifier key
} full_viewing_key_t;
} full_viewing_key_t;

typedef struct {
uint8_t ak[AK_SIZE];
uint8_t ask[ASK_SIZE];
uint8_t nk[NK_SIZE]; // nullifier deriving key
uint8_t nsk[NSK_SIZE];
uint8_t ovk[OVK_SIZE]; // outgoing viewing key
uint8_t dk[DK_SIZE]; // diversifier key
} all_keys_t;

0 comments on commit 261bd49

Please sign in to comment.