Skip to content

Commit

Permalink
Merge pull request #63 from Zondax/feat/masp_wrapper_sig
Browse files Browse the repository at this point in the history
Fixing issues and improve Masp
  • Loading branch information
chcmedeiros authored Sep 17, 2024
2 parents 86dffc6 + 70a37c8 commit c8bba31
Show file tree
Hide file tree
Showing 273 changed files with 510 additions and 256 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
13 changes: 8 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 Down Expand Up @@ -315,9 +318,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 Down
2 changes: 1 addition & 1 deletion app/src/coin.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ 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 APDU_CODE_CHECK_SIGN_TR_FAIL 0x6999
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
63 changes: 30 additions & 33 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 @@ -626,32 +647,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 +659,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 +676,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 +902,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
60 changes: 55 additions & 5 deletions app/src/crypto_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -590,9 +590,7 @@ parser_error_t computePkd(const uint8_t ivk[KEY_LENGTH], const uint8_t diversifi
blake2s_update(&state, diversifier, DIVERSIFIER_LENGTH);
blake2s_final(&state, hash, KEY_LENGTH);

zemu_log_stack("computePkd got hash");
CHECK_ERROR(get_pkd(ivk, hash, pk_d));
zemu_log_stack("computePkd after get_pkd");
return parser_ok;
}

Expand Down Expand Up @@ -621,7 +619,7 @@ parser_error_t computeValueCommitment(uint64_t value, uint8_t *rcv, uint8_t *ide
blake2s_final(&state, hash, KEY_LENGTH);

uint8_t scalar[32] = {0};
CHECK_ERROR(scalar_multiplication(rcv, ValueCommitmentRandomnessGenerator, scalar));
CHECK_ERROR(parser_scalar_multiplication(rcv, ValueCommitmentRandomnessGenerator, scalar));
CHECK_ERROR(add_points(hash, value_bytes, scalar, cv));

return parser_ok;
Expand All @@ -634,10 +632,62 @@ parser_error_t computeRk(keys_t *keys, uint8_t *alpha, uint8_t *rk) {
}
uint8_t rsk[KEY_LENGTH] = {0};
// get randomized secret
CHECK_ERROR(randomized_secret_from_seed(keys->ask, alpha, rsk));
CHECK_ERROR(parser_randomized_secret_from_seed(keys->ask, alpha, rsk));

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

return parser_ok;
}

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

// This fuctnion will allow to test the rust ones in cpp_tests
parser_error_t parser_scalar_multiplication(const uint8_t input[32], constant_key_t key, uint8_t output[32]) {
if (input == NULL || output == NULL) {
return parser_no_data;
}

return scalar_multiplication(input, key, output);
}

parser_error_t parser_compute_sbar(const uint8_t s[32], uint8_t r[32], uint8_t rsk[32], uint8_t sbar[32]) {
if (s == NULL || r == NULL || rsk == NULL || sbar == NULL) {
return parser_no_data;
}

return compute_sbar(s, r, rsk, sbar);
}

parser_error_t parser_randomized_secret_from_seed(const uint8_t ask[32], const uint8_t alpha[32], uint8_t output[32]) {
if (ask == NULL || alpha == NULL || output == NULL) {
return parser_no_data;
}

return randomized_secret_from_seed(ask, alpha, output);
}
4 changes: 4 additions & 0 deletions app/src/crypto_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ parser_error_t computeRk(keys_t *keys, uint8_t *alpha, uint8_t *rk);
parser_error_t crypto_encodeLargeBech32( const uint8_t *address, size_t addressLen, uint8_t *output, size_t outputLen, bool paymentAddr);
parser_error_t crypto_encodeAltAddress(const AddressAlt *addr, char *address, uint16_t addressLen);
parser_error_t derive_asset_type(const masp_asset_data_t *asset_data, uint8_t *identifier, uint8_t *nonce);
parser_error_t h_star(uint8_t *a, uint16_t a_len, uint8_t *b, uint16_t b_len, uint8_t *output);
parser_error_t parser_scalar_multiplication(const uint8_t input[32], constant_key_t key, uint8_t output[32]);
parser_error_t parser_compute_sbar(const uint8_t s[32], uint8_t r[32], uint8_t rsk[32], uint8_t sbar[32]);
parser_error_t parser_randomized_secret_from_seed(const uint8_t ask[32], const uint8_t alpha[32], uint8_t output[32]);
#ifdef __cplusplus
}
#endif
23 changes: 23 additions & 0 deletions app/src/parser_impl_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,29 @@ parser_error_t readFieldSizeU16(parser_context_t *ctx, uint16_t *size) {
return parser_ok;
}

parser_error_t readCompactSize(parser_context_t *ctx, uint64_t *result) {
uint8_t tag = 0;
uint16_t tmp16 = 0;
uint32_t tmp32 = 0;
CHECK_ERROR(readByte(ctx, &tag))
switch(tag) {
case 253:
CHECK_ERROR(readUint16(ctx, &tmp16))
*result = (uint64_t)tmp16;
break;
case 254:
CHECK_ERROR(readUint32(ctx, &tmp32))
*result = (uint64_t)tmp32;
break;
case 255:
CHECK_ERROR(readUint64(ctx, result))
break;
default:
*result = (uint64_t)tag;
}
return parser_ok;
}

parser_error_t checkTag(parser_context_t *ctx, uint8_t expectedTag) {
uint8_t tmpTag = 0;
CHECK_ERROR(readByte(ctx, &tmpTag))
Expand Down
1 change: 1 addition & 0 deletions app/src/parser_impl_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ parser_error_t readBytesSize(parser_context_t *ctx, uint8_t *output, uint16_t ou
parser_error_t readUint16(parser_context_t *ctx, uint16_t *value);
parser_error_t readUint32(parser_context_t *ctx, uint32_t *value);
parser_error_t readUint64(parser_context_t *ctx, uint64_t *value);
parser_error_t readCompactSize(parser_context_t *ctx, uint64_t *result);

parser_error_t readFieldSize(parser_context_t *ctx, uint32_t *size);
parser_error_t readFieldSizeU16(parser_context_t *ctx, uint16_t *size);
Expand Down
Loading

0 comments on commit c8bba31

Please sign in to comment.