Skip to content

Commit

Permalink
Merge pull request #64 from Zondax/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
chcmedeiros authored Sep 17, 2024
2 parents 6e0ac0f + 4f0be47 commit c52229a
Show file tree
Hide file tree
Showing 293 changed files with 46,564 additions and 44,967 deletions.
11 changes: 1 addition & 10 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
[submodule "deps/ledger-zxlib"]
path = deps/ledger-zxlib
url = https://github.com/Zondax/ledger-zxlib.git
[submodule "deps/nanox-secure-sdk"]
path = deps/nanox-secure-sdk
url = https://github.com/LedgerHQ/ledger-secure-sdk
[submodule "deps/nanosplus-secure-sdk"]
path = deps/nanosplus-secure-sdk
url = https://github.com/LedgerHQ/ledger-secure-sdk
[submodule "deps/ledger-secure-sdk"]
path = deps/ledger-secure-sdk
url = https://github.com/LedgerHQ/ledger-secure-sdk
[submodule "deps/blake2"]
path = deps/blake2
url = https://github.com/Zondax/BLAKE2.git
[submodule "deps/nanos-secure-sdk"]
path = deps/nanos-secure-sdk
url = https://github.com/LedgerHQ/ledger-secure-sdk
url = https://github.com/Zondax/BLAKE2.git
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ ifeq ($(BOLOS_SDK),)
# In this case, there is not predefined SDK and we run dockerized
# When not using the SDK, we override and build the XL complete app
ZXLIB_COMPILE_STAX ?= 1
PRODUCTION_BUILD ?= 0
PRODUCTION_BUILD ?= 1
include $(CURDIR)/deps/ledger-zxlib/dockerized_build.mk

else
Expand Down
2 changes: 1 addition & 1 deletion app/Makefile.version
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ APPVERSION_M=0
# This is the `spec_version` field of `Runtime`
APPVERSION_N=0
# This is the patch version of this release
APPVERSION_P=27
APPVERSION_P=28
24 changes: 19 additions & 5 deletions app/src/apdu_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ __Z_INLINE void handleSignTransaction(volatile uint32_t *flags, volatile uint32_
CHECK_APP_CANARY()

if (error_msg != NULL) {
transaction_reset();
const int error_msg_length = strnlen(error_msg, sizeof(G_io_apdu_buffer));
memcpy(G_io_apdu_buffer, error_msg, error_msg_length);
*tx += (error_msg_length);
Expand Down Expand Up @@ -145,8 +146,8 @@ __Z_INLINE void handleGetAddr(volatile uint32_t *flags, volatile uint32_t *tx, u
THROW(APDU_CODE_OK);
}
#if defined(COMPILE_MASP)
__Z_INLINE void handleSignMasp(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
ZEMU_LOGF(50, "handleSignMasp\n")
__Z_INLINE void handleSignMaspSpends(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
ZEMU_LOGF(50, "handleSignMaspSpends\n")
if (!process_chunk(tx, rx)) {
THROW(APDU_CODE_OK);
}
Expand All @@ -156,14 +157,15 @@ __Z_INLINE void handleSignMasp(volatile uint32_t *flags, volatile uint32_t *tx,
CHECK_APP_CANARY()

if (error_msg != NULL) {
transaction_reset();
const int error_msg_length = strnlen(error_msg, sizeof(G_io_apdu_buffer));
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_masp);
view_review_init(tx_getItem, tx_getNumItems, app_sign_masp_spends);
view_review_show(REVIEW_TXN);
*flags |= IO_ASYNCH_REPLY;
}
Expand Down Expand Up @@ -202,6 +204,7 @@ __Z_INLINE void handleComputeMaspRand(__Z_UNUSED volatile uint32_t *flags, volat
*tx = 0;
zxerr_t zxerr = app_fill_randomness(type);
if (zxerr != zxerr_ok) {
transaction_reset();
*tx = 0;
THROW(APDU_CODE_DATA_INVALID);
}
Expand All @@ -221,6 +224,12 @@ __Z_INLINE void handleExtractSpendSign(__Z_UNUSED volatile uint32_t *flags, vola
THROW(APDU_CODE_OK);
}

__Z_INLINE void handleCleanRandomnessBuffers(__Z_UNUSED volatile uint32_t *flags, volatile uint32_t *tx, __Z_UNUSED uint32_t rx) {
*tx = 0;
transaction_reset();
THROW(APDU_CODE_OK);
}

#endif

__Z_INLINE void handle_getversion(__Z_UNUSED volatile uint32_t *flags, volatile uint32_t *tx)
Expand Down Expand Up @@ -315,9 +324,9 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
break;
}

case INS_SIGN_MASP: {
case INS_SIGN_MASP_SPENDS: {
CHECK_PIN_VALIDATED()
handleSignMasp(flags, tx, rx);
handleSignMaspSpends(flags, tx, rx);
break;
}

Expand All @@ -326,6 +335,11 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
handleExtractSpendSign(flags, tx, rx);
break;
}
case INS_CLEAN_BUFFERS: {
CHECK_PIN_VALIDATED()
handleCleanRandomnessBuffers(flags, tx, rx);
break;
}
#endif
#if defined(APP_TESTING)
case INS_TEST: {
Expand Down
3 changes: 2 additions & 1 deletion app/src/coin.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,9 @@ typedef enum {
#define INS_GET_SPEND_RAND 0x04
#define INS_GET_OUTPUT_RAND 0x05
#define INS_GET_CONVERT_RAND 0x06
#define INS_SIGN_MASP 0x07
#define INS_SIGN_MASP_SPENDS 0x07
#define INS_EXTRACT_SPEND_SIGN 0x08
#define INS_CLEAN_BUFFERS 0x09

#define APDU_CODE_CHECK_SIGN_TR_FAIL 0x6999
#ifdef __cplusplus
Expand Down
8 changes: 5 additions & 3 deletions app/src/common/actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,21 @@ __Z_INLINE void app_sign() {
const zxerr_t err = crypto_sign(txObj, G_io_apdu_buffer, sizeof(G_io_apdu_buffer) - 2);

if (err != zxerr_ok) {
transaction_reset();
MEMZERO(G_io_apdu_buffer, sizeof(G_io_apdu_buffer));
set_code(G_io_apdu_buffer, 0, APDU_CODE_SIGN_VERIFY_ERROR);
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
} else {
transaction_reset();
const uint16_t responseLen = PK_LEN_25519_PLUS_TAG + 2 * SALT_LEN + 2 * SIG_LEN_25519_PLUS_TAG + 2 + 10;
set_code(G_io_apdu_buffer, responseLen, APDU_CODE_OK);
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, responseLen + 2);
}
}

__Z_INLINE void app_sign_masp() {
const parser_tx_t *txObj = tx_get_txObject();
const zxerr_t err = crypto_sign_masp(txObj, G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3);
__Z_INLINE void app_sign_masp_spends() {
parser_tx_t *txObj = tx_get_txObject();
const zxerr_t err = crypto_sign_masp_spends(txObj, G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3);

if (err != zxerr_ok) {
transaction_reset();
Expand Down
1 change: 1 addition & 0 deletions app/src/common/parser_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ typedef enum {
parser_invalid_number_of_converts,
parser_invalid_rk,
parser_invalid_cv,
parser_invalid_target_hash,
} parser_error_t;

typedef struct {
Expand Down
68 changes: 33 additions & 35 deletions app/src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

#define CHECK_PARSER_OK(CALL) \
do { \
cx_err_t __cx_err = CALL; \
parser_error_t __cx_err = CALL; \
if (__cx_err != parser_ok) { \
return zxerr_unknown; \
} \
Expand Down Expand Up @@ -310,6 +310,16 @@ static zxerr_t crypto_addTxnHashes(const parser_tx_t *txObj, concatenated_hashes
return zxerr_ok;
}

zxerr_t crypto_hashMaspSection(const uint8_t *input, uint64_t inputLen, uint8_t* output) {
if (input == NULL || output == NULL) {
return zxerr_invalid_crypto_settings;
}
cx_sha256_t sha256 = {0};
cx_sha256_init(&sha256);
CHECK_CX_OK(cx_sha256_update(&sha256, input, (size_t)inputLen));
CHECK_CX_OK(cx_sha256_final(&sha256, output));
return zxerr_ok;
}

zxerr_t crypto_sign(const parser_tx_t *txObj, uint8_t *output, uint16_t outputLen) {
const uint16_t minimumBufferSize = PK_LEN_25519_PLUS_TAG + 2 * SALT_LEN + 2 * SIG_LEN_25519_PLUS_TAG + 2 + 10;
Expand All @@ -321,7 +331,7 @@ zxerr_t crypto_sign(const parser_tx_t *txObj, uint8_t *output, uint16_t outputLe
CHECK_ZXERR(crypto_extractPublicKey_ed25519(output + 1, PK_LEN_25519))
const bytes_t pubkey = {.ptr = output, .len = PK_LEN_25519_PLUS_TAG};

// Hashes: code, data, (initAcc | initVali | updateVP = 1 / initProp = 2), raw_signature, header ---> MaxHashes = 6
// Hashes: code, data, (initAcc | initVali | updateVP = 1 / initProp = 2), raw_signature, header, masp ---> MaxHashes = 6
uint8_t hashes_buffer[MAX_SIGNATURE_HASHES * HASH_LEN] = {0};
uint8_t indices_buffer[MAX_SIGNATURE_HASHES] = {0};
concatenated_hashes_t section_hashes = {
Expand Down Expand Up @@ -400,6 +410,17 @@ zxerr_t crypto_sign(const parser_tx_t *txObj, uint8_t *output, uint16_t outputLe
section_hashes.hashesLen += 2;
signature_section.hashes.hashesLen += 2;

// Include Masp hash in the signature if it's there
if (txObj->transaction.isMasp) {
const uint8_t *maspSection = txObj->transaction.sections.maspTx.masptx_ptr;
uint64_t maspSectionLen = txObj->transaction.sections.maspTx.masptx_len;
uint8_t *maspHash = section_hashes.hashes.ptr + (section_hashes.hashesLen * HASH_LEN);
CHECK_ZXERR(crypto_hashMaspSection(maspSection, maspSectionLen, maspHash))
section_hashes.indices.ptr[section_hashes.hashesLen] = txObj->transaction.maspTx_idx;
section_hashes.hashesLen++;
signature_section.hashes.hashesLen++;
}

// Include the memo section hash in the signature if it's there
if (txObj->transaction.header.memoSection != NULL) {
const section_t *memo = txObj->transaction.header.memoSection;
Expand Down Expand Up @@ -520,13 +541,14 @@ __Z_INLINE zxerr_t copyKeys(keys_t *saplingKeys, key_kind_e requestedKeys, uint8
break;

case ViewKeys:
if (outputLen < 4 * KEY_LENGTH) {
if (outputLen < 5 * KEY_LENGTH) {
return zxerr_buffer_too_small;
}
memcpy(output, saplingKeys->ak, KEY_LENGTH);
memcpy(output + KEY_LENGTH, saplingKeys->nk, KEY_LENGTH);
memcpy(output + 2 * KEY_LENGTH, saplingKeys->ovk, KEY_LENGTH);
memcpy(output + 3 * KEY_LENGTH, saplingKeys->ivk, KEY_LENGTH);
memcpy(output + 4 * KEY_LENGTH, saplingKeys->dk, KEY_LENGTH);
break;

case ProofGenerationKey:
Expand Down Expand Up @@ -612,7 +634,7 @@ zxerr_t crypto_fillMASP(uint8_t *buffer, uint16_t bufferLen, uint16_t *cmdRespon
break;

case ViewKeys:
*cmdResponseLen = 4 * KEY_LENGTH;
*cmdResponseLen = 5 * KEY_LENGTH;
break;

case ProofGenerationKey:
Expand All @@ -626,32 +648,8 @@ zxerr_t crypto_fillMASP(uint8_t *buffer, uint16_t bufferLen, uint16_t *cmdRespon
return zxerr_ok;
}

static parser_error_t h_star(uint8_t *a, uint16_t a_len, uint8_t *b, uint16_t b_len, uint8_t *output) {
if (a == NULL || b == NULL || output == NULL) {
return parser_no_data;
}

uint8_t hash[BLAKE2B_OUTPUT_LEN] = {0};
#if defined(LEDGER_SPECIFIC)
cx_blake2b_t ctx = {0};
ASSERT_CX_OK(cx_blake2b_init2_no_throw(&ctx, BLAKE2B_OUTPUT_LEN, NULL, 0, (uint8_t *)SIGNING_REDJUBJUB,
sizeof(SIGNING_REDJUBJUB)));
ASSERT_CX_OK(cx_blake2b_update(&ctx, a, a_len));
ASSERT_CX_OK(cx_blake2b_update(&ctx, b, b_len));
cx_blake2b_final(&ctx, hash);
#else
blake2b_state state = {0};
blake2b_init_with_personalization(&state, BLAKE2B_OUTPUT_LEN, (const uint8_t *)SIGNING_REDJUBJUB,
sizeof(SIGNING_REDJUBJUB));
blake2b_update(&state, a, a_len);
blake2b_update(&state, b, b_len);
blake2b_final(&state, hash, BLAKE2B_OUTPUT_LEN);
#endif

from_bytes_wide(hash, output);

return parser_ok;
}
// https://github.com/anoma/masp/blob/8d83b172698098fba393006016072bc201ed9ab7/masp_primitives/src/sapling.rs#L170
// https://github.com/anoma/masp/blob/main/masp_primitives/src/sapling/redjubjub.rs#L136
static zxerr_t sign_sapling_spend(keys_t *keys, uint8_t alpha[static KEY_LENGTH], uint8_t sign_hash[static KEY_LENGTH], uint8_t *signature) {
if (alpha == NULL || sign_hash == NULL || signature == NULL) {
return zxerr_no_data;
Expand All @@ -662,10 +660,10 @@ static zxerr_t sign_sapling_spend(keys_t *keys, uint8_t alpha[static KEY_LENGTH]
uint8_t rk[KEY_LENGTH] = {0};

// get randomized secret
randomized_secret_from_seed(keys->ask, alpha, rsk);
CHECK_PARSER_OK(parser_randomized_secret_from_seed(keys->ask, alpha, rsk));

//rsk to rk
scalar_multiplication(rsk, SpendingKeyGenerator, rk);
CHECK_PARSER_OK(parser_scalar_multiplication(rsk, SpendingKeyGenerator, rk));

// sign
MEMCPY(data_to_be_signed, rk, KEY_LENGTH);
Expand All @@ -679,13 +677,13 @@ static zxerr_t sign_sapling_spend(keys_t *keys, uint8_t alpha[static KEY_LENGTH]
uint8_t r[32] = {0};
uint8_t rbar[32] = {0};
CHECK_PARSER_OK(h_star(rng, sizeof(rng), data_to_be_signed, sizeof(data_to_be_signed), r));
CHECK_PARSER_OK(scalar_multiplication(r, SpendingKeyGenerator, rbar));
CHECK_PARSER_OK(parser_scalar_multiplication(r, SpendingKeyGenerator, rbar));

//compute s and sbar
uint8_t s[32] = {0};
uint8_t sbar[32] = {0};
CHECK_PARSER_OK(h_star(rbar, sizeof(rbar), data_to_be_signed, sizeof(data_to_be_signed), s));
CHECK_PARSER_OK(compute_sbar(s, r, rsk, sbar));
CHECK_PARSER_OK(parser_compute_sbar(s, r, rsk, sbar));

MEMCPY(signature, rbar, HASH_LEN);
MEMCPY(signature + HASH_LEN, sbar, HASH_LEN);
Expand Down Expand Up @@ -905,7 +903,7 @@ zxerr_t crypto_hash_messagebuffer(uint8_t *buffer, uint16_t bufferLen,
return zxerr_ok;
}

zxerr_t crypto_sign_masp(const parser_tx_t *txObj, uint8_t *output, uint16_t outputLen) {
zxerr_t crypto_sign_masp_spends(parser_tx_t *txObj, uint8_t *output, uint16_t outputLen) {
if (txObj == NULL || output == NULL || outputLen < ED25519_SIGNATURE_SIZE) {
return zxerr_unknown;
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extern uint32_t hdPath[HDPATH_LEN_DEFAULT];
zxerr_t crypto_fillAddress(signing_key_type_e addressKind, uint8_t *buffer, uint16_t bufferLen, uint16_t *cmdResponseLen);
zxerr_t crypto_sign(const parser_tx_t *txObj, uint8_t *output, uint16_t outputLen);
zxerr_t crypto_fillMASP(uint8_t *buffer, uint16_t bufferLen, uint16_t *cmdResponseLen, key_kind_e requestedKey);
zxerr_t crypto_sign_masp(const parser_tx_t *txObj, uint8_t *output, uint16_t outputLen);
zxerr_t crypto_sign_masp_spends(parser_tx_t *txObj, uint8_t *output, uint16_t outputLen);
zxerr_t crypto_extract_spend_signature(uint8_t *buffer, uint16_t bufferLen, uint16_t *cmdResponseLen);
zxerr_t crypto_computeRandomness(masp_type_e type, uint8_t *out, uint16_t outLen, uint16_t *replyLen);
#ifdef __cplusplus
Expand Down
Loading

0 comments on commit c52229a

Please sign in to comment.