From 1782c0088b067ae7275c22658e326378f0481d9c Mon Sep 17 00:00:00 2001 From: becominginsane Date: Fri, 27 Oct 2023 03:14:31 +0800 Subject: [PATCH 1/3] style: clang-format --- app/rust/include/rslib.h | 75 +- app/src/addr.c | 130 +- app/src/addr.h | 35 +- app/src/apdu_handler.c | 1499 ++++++++++---------- app/src/c_api/rust.c | 244 ++-- app/src/chacha.c | 182 +-- app/src/chacha.h | 10 +- app/src/coin.h | 156 +-- app/src/common/actions.c | 28 +- app/src/common/actions.h | 78 +- app/src/common/main.c | 61 +- app/src/common/tx.c | 133 +- app/src/common/tx.h | 37 +- app/src/constants.h | 201 ++- app/src/crypto.c | 2627 ++++++++++++++++++----------------- app/src/crypto.h | 124 +- app/src/index_NU5.h | 57 +- app/src/index_sapling.c | 48 +- app/src/index_sapling.h | 151 +- app/src/jubjub.c | 574 ++++---- app/src/jubjub.h | 83 +- app/src/key.c | 151 +- app/src/key.h | 35 +- app/src/nvdata.c | 532 ++++--- app/src/nvdata.h | 136 +- app/src/parser.c | 719 +++++----- app/src/parser.h | 63 +- app/src/parser_common.h | 121 +- app/src/parser_impl.c | 148 +- app/src/parser_impl.h | 167 ++- app/src/parser_txdef.h | 34 +- app/src/sighash.c | 318 +++-- app/src/sighash.h | 47 +- app/src/txid.c | 708 +++++----- app/src/txid.h | 32 +- app/src/zcash_apdu_errors.h | 58 +- 36 files changed, 5045 insertions(+), 4757 deletions(-) diff --git a/app/rust/include/rslib.h b/app/rust/include/rslib.h index d4f36879..05254517 100644 --- a/app/rust/include/rslib.h +++ b/app/rust/include/rslib.h @@ -8,26 +8,39 @@ /****************************** others * ********************************************************************************/ -//ZIP32 functions -void get_pkd(const uint8_t *seed_ptr, const uint32_t pos, const uint8_t *diversifier_ptr, uint8_t *pkd); +// ZIP32 functions +void get_pkd(const uint8_t *seed_ptr, const uint32_t pos, + const uint8_t *diversifier_ptr, uint8_t *pkd); -void get_pkd_from_seed(const uint8_t *seed_ptr, const uint32_t pos, const uint8_t *start_index, uint8_t *diversifier_ptr, uint8_t *pkd); +void get_pkd_from_seed(const uint8_t *seed_ptr, const uint32_t pos, + const uint8_t *start_index, uint8_t *diversifier_ptr, + uint8_t *pkd); void get_diversifier_list(const uint8_t *sk_ptr, uint8_t *diversifier_list); -void get_diversifier_fromlist(const uint8_t *diversifier_list, uint8_t *diversifier); +void get_diversifier_fromlist(const uint8_t *diversifier_list, + uint8_t *diversifier); bool is_valid_diversifier(const uint8_t *diversifier); -void get_diversifier_list_withstartindex(const uint8_t *seed_ptr, const uint32_t pos, const uint8_t *startindex, uint8_t *diversifier_list); +void get_diversifier_list_withstartindex(const uint8_t *seed_ptr, + const uint32_t pos, + const uint8_t *startindex, + uint8_t *diversifier_list); -void get_default_diversifier_list_withstartindex(const uint8_t *seed_ptr, const uint32_t pos, uint8_t *startindex, uint8_t *diversifier_list); +void get_default_diversifier_list_withstartindex(const uint8_t *seed_ptr, + const uint32_t pos, + uint8_t *startindex, + uint8_t *diversifier_list); -void get_default_diversifier_without_start_index(const uint8_t *see_ptr, const uint32_t pos, uint8_t *default_diversifier); +void get_default_diversifier_without_start_index(const uint8_t *see_ptr, + const uint32_t pos, + uint8_t *default_diversifier); void zip32_master(const uint8_t *seed_ptr, uint8_t *sk_ptr, uint8_t *dk_ptr); -void zip32_child_ask_nsk(const uint8_t *seed_ptr, uint8_t *ask, uint8_t *nsk, const uint32_t pos); +void zip32_child_ask_nsk(const uint8_t *seed_ptr, uint8_t *ask, uint8_t *nsk, + const uint32_t pos); void zip32_nsk_from_seed(const uint8_t *seed_ptr, uint8_t *nsk); @@ -37,42 +50,56 @@ void zip32_ovk(const uint8_t *seed_ptr, uint8_t *ovk, const uint32_t pos); void zip32_fvk(const uint8_t *seed_ptr, uint8_t *fvk, const uint32_t pos); -void zip32_child_proof_key(const uint8_t *seed_ptr, uint8_t *ak_ptr, uint8_t *nsk_ptr, const uint32_t pos); +void zip32_child_proof_key(const uint8_t *seed_ptr, uint8_t *ak_ptr, + uint8_t *nsk_ptr, const uint32_t pos); -//Rseed -void rseed_get_esk_epk(const uint8_t *seed_ptr, uint8_t *d_ptr, uint8_t *output_esk_ptr, uint8_t *output_epk_ptr); +// Rseed +void rseed_get_esk_epk(const uint8_t *seed_ptr, uint8_t *d_ptr, + uint8_t *output_esk_ptr, uint8_t *output_epk_ptr); void rseed_get_rcm(const uint8_t *input, uint8_t *output_ptr); -//Commitments -void compute_note_commitment(uint8_t *inputptr, const uint8_t *rcmptr,const uint64_t value,const uint8_t *diversifier_ptr, const uint8_t *pkd); +// Commitments +void compute_note_commitment(uint8_t *inputptr, const uint8_t *rcmptr, + const uint64_t value, + const uint8_t *diversifier_ptr, + const uint8_t *pkd); -void compute_note_commitment_fullpoint(uint8_t *inputptr, const uint8_t *rcmptr,const uint64_t value, const uint8_t *diversifier_ptr, const uint8_t *pkd); +void compute_note_commitment_fullpoint(uint8_t *inputptr, const uint8_t *rcmptr, + const uint64_t value, + const uint8_t *diversifier_ptr, + const uint8_t *pkd); -void compute_value_commitment(const uint64_t value, const uint8_t *rcmptr, uint8_t *output); +void compute_value_commitment(const uint64_t value, const uint8_t *rcmptr, + uint8_t *output); -void compute_nullifier(uint8_t *ncmptr, uint64_t pos, const uint8_t *nsk_ptr, uint8_t *outputptr); +void compute_nullifier(uint8_t *ncmptr, uint64_t pos, const uint8_t *nsk_ptr, + uint8_t *outputptr); -//Note encryption +// Note encryption void blake2b_prf(uint8_t *inputptr, uint8_t *outptr); -void ka_to_key(uint8_t *esk_ptr, uint8_t *pkd_ptr, uint8_t *epk_ptr, uint8_t *output_ptr); +void ka_to_key(uint8_t *esk_ptr, uint8_t *pkd_ptr, uint8_t *epk_ptr, + uint8_t *output_ptr); -void prepare_enccompact_input(uint8_t *d, uint64_t value, uint8_t *rcm, uint8_t memotype, uint8_t *output); +void prepare_enccompact_input(uint8_t *d, uint64_t value, uint8_t *rcm, + uint8_t memotype, uint8_t *output); -//RedJubjub +// RedJubjub void random_fr(uint8_t *alpha_ptr); -void randomized_secret_from_seed(uint8_t *seed_ptr, uint32_t pos, uint8_t *alpha_ptr, uint8_t *output_ptr); +void randomized_secret_from_seed(uint8_t *seed_ptr, uint32_t pos, + uint8_t *alpha_ptr, uint8_t *output_ptr); void get_rk(uint8_t *ask_ptr, uint8_t *alpha_ptr, uint8_t *output_ptr); -void rsk_to_rk(const uint8_t* rsk_ptr, uint8_t* rk_ptr); +void rsk_to_rk(const uint8_t *rsk_ptr, uint8_t *rk_ptr); void randomize_pk(uint8_t *alpha_ptr, uint8_t *pk_ptr); void sign_redjubjub(uint8_t *key_ptr, uint8_t *msg_ptr, uint8_t *out_ptr); -//Session key -void sessionkey_agree(uint8_t *scalar_ptr, uint8_t *point_ptr, uint8_t *output_ptr); +// Session key +void sessionkey_agree(uint8_t *scalar_ptr, uint8_t *point_ptr, + uint8_t *output_ptr); void pubkey_gen(uint8_t *scalar_ptr, uint8_t *output_ptr); diff --git a/app/src/addr.c b/app/src/addr.c index 02984cea..552061c0 100644 --- a/app/src/addr.c +++ b/app/src/addr.c @@ -1,79 +1,81 @@ /******************************************************************************* -* (c) 2018 - 2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 - 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ -#include +#include "actions.h" +#include "app_mode.h" #include "coin.h" +#include "crypto.h" #include "zxerror.h" -#include "zxmacros.h" #include "zxformat.h" -#include "app_mode.h" -#include "crypto.h" -#include "actions.h" +#include "zxmacros.h" +#include zxerr_t addr_getNumItems(uint8_t *num_items) { - zemu_log_stack("addr_getNumItems"); - *num_items = 1; - if (app_mode_expert()) { - *num_items = 2; - } - return zxerr_ok; + zemu_log_stack("addr_getNumItems"); + *num_items = 1; + if (app_mode_expert()) { + *num_items = 2; + } + return zxerr_ok; } -zxerr_t addr_getItem(int8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outVal, uint16_t outValLen, - uint8_t pageIdx, uint8_t *pageCount) { - ZEMU_LOGF(200, "[addr_getItem] %d/%d\n", displayIdx, pageIdx) +zxerr_t addr_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, + char *outVal, uint16_t outValLen, uint8_t pageIdx, + uint8_t *pageCount) { + ZEMU_LOGF(200, "[addr_getItem] %d/%d\n", displayIdx, pageIdx) - switch (displayIdx) { - case 0: - switch (action_addrResponse.kind) { - case addr_secp256k1: - snprintf(outKey, outKeyLen, "Unshielded"); - pageString(outVal, outValLen, (char *) (G_io_apdu_buffer + VIEW_ADDRESS_OFFSET_SECP256K1), pageIdx, - pageCount); - return zxerr_ok; + switch (displayIdx) { + case 0: + switch (action_addrResponse.kind) { + case addr_secp256k1: + snprintf(outKey, outKeyLen, "Unshielded"); + pageString(outVal, outValLen, + (char *)(G_io_apdu_buffer + VIEW_ADDRESS_OFFSET_SECP256K1), + pageIdx, pageCount); + return zxerr_ok; - case addr_sapling: - snprintf(outKey, outKeyLen, "Shielded"); - pageString(outVal, outValLen, (char *) (G_io_apdu_buffer + VIEW_ADDRESS_OFFSET_SAPLING), pageIdx, - pageCount); - return zxerr_ok; + case addr_sapling: + snprintf(outKey, outKeyLen, "Shielded"); + pageString(outVal, outValLen, + (char *)(G_io_apdu_buffer + VIEW_ADDRESS_OFFSET_SAPLING), + pageIdx, pageCount); + return zxerr_ok; - case addr_sapling_div: - snprintf(outKey, outKeyLen, "Shielded with div"); - pageString(outVal, outValLen, (char *) (G_io_apdu_buffer + VIEW_ADDRESS_OFFSET_SAPLING), pageIdx, - pageCount); - return zxerr_ok; + case addr_sapling_div: + snprintf(outKey, outKeyLen, "Shielded with div"); + pageString(outVal, outValLen, + (char *)(G_io_apdu_buffer + VIEW_ADDRESS_OFFSET_SAPLING), + pageIdx, pageCount); + return zxerr_ok; - default: - return zxerr_no_data; - } - case 1: { - if (!app_mode_expert()) { - return zxerr_no_data; - } - - snprintf(outKey, outKeyLen, "Your Path"); - char buffer[300]; - bip32_to_str(buffer, sizeof(buffer), hdPath, HDPATH_LEN_DEFAULT); - pageString(outVal, outValLen, buffer, pageIdx, pageCount); - return zxerr_ok; - } - default: - return zxerr_no_data; + default: + return zxerr_no_data; + } + case 1: { + if (!app_mode_expert()) { + return zxerr_no_data; } + + snprintf(outKey, outKeyLen, "Your Path"); + char buffer[300]; + bip32_to_str(buffer, sizeof(buffer), hdPath, HDPATH_LEN_DEFAULT); + pageString(outVal, outValLen, buffer, pageIdx, pageCount); + return zxerr_ok; + } + default: + return zxerr_no_data; + } } diff --git a/app/src/addr.h b/app/src/addr.h index c7db769e..aaa80629 100644 --- a/app/src/addr.h +++ b/app/src/addr.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2018 = 2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 = 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -24,10 +24,9 @@ extern "C" { zxerr_t addr_getNumItems(uint8_t *num_items); /// Gets an specific item from the address view (including paging) -zxerr_t addr_getItem(int8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outValue, uint16_t outValueLen, - uint8_t pageIdx, uint8_t *pageCount); +zxerr_t addr_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, + char *outValue, uint16_t outValueLen, uint8_t pageIdx, + uint8_t *pageCount); #ifdef __cplusplus } diff --git a/app/src/apdu_handler.c b/app/src/apdu_handler.c index 2d5f703a..0221a046 100644 --- a/app/src/apdu_handler.c +++ b/app/src/apdu_handler.c @@ -1,347 +1,357 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* (c) 2016 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * (c) 2016 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include "app_main.h" -#include -#include #include +#include +#include #include -#include "view.h" #include "actions.h" -#include "tx.h" #include "addr.h" -#include "crypto.h" -#include "coin.h" -#include "zxmacros.h" #include "app_mode.h" +#include "coin.h" +#include "crypto.h" +#include "tx.h" +#include "view.h" #include "zcash_apdu_errors.h" +#include "zxmacros.h" #include "key.h" -#include "parser.h" #include "nvdata.h" +#include "parser.h" #include "view_internal.h" __Z_INLINE void handle_getversion(volatile uint32_t *tx) { #ifdef DEBUG - G_io_apdu_buffer[0] = 0xFF; + G_io_apdu_buffer[0] = 0xFF; #else - G_io_apdu_buffer[0] = 0; + G_io_apdu_buffer[0] = 0; #endif - G_io_apdu_buffer[1] = LEDGER_MAJOR_VERSION; - G_io_apdu_buffer[2] = LEDGER_MINOR_VERSION; - G_io_apdu_buffer[3] = LEDGER_PATCH_VERSION; - // SDK won't reply any APDU message if the device is locked --> Set device_locked = false - G_io_apdu_buffer[4] = 0; - - G_io_apdu_buffer[5] = (TARGET_ID >> 24) & 0xFF; - G_io_apdu_buffer[6] = (TARGET_ID >> 16) & 0xFF; - G_io_apdu_buffer[7] = (TARGET_ID >> 8) & 0xFF; - G_io_apdu_buffer[8] = (TARGET_ID >> 0) & 0xFF; - - *tx += 9; - THROW(APDU_CODE_OK); + G_io_apdu_buffer[1] = LEDGER_MAJOR_VERSION; + G_io_apdu_buffer[2] = LEDGER_MINOR_VERSION; + G_io_apdu_buffer[3] = LEDGER_PATCH_VERSION; + // SDK won't reply any APDU message if the device is locked --> Set + // device_locked = false + G_io_apdu_buffer[4] = 0; + + G_io_apdu_buffer[5] = (TARGET_ID >> 24) & 0xFF; + G_io_apdu_buffer[6] = (TARGET_ID >> 16) & 0xFF; + G_io_apdu_buffer[7] = (TARGET_ID >> 8) & 0xFF; + G_io_apdu_buffer[8] = (TARGET_ID >> 0) & 0xFF; + + *tx += 9; + THROW(APDU_CODE_OK); } __Z_INLINE void extractHDPath(uint32_t rx, uint32_t offset) { - if ((rx - offset) < sizeof(uint32_t) * HDPATH_LEN_DEFAULT) { - THROW(APDU_CODE_WRONG_LENGTH); - } + if ((rx - offset) < sizeof(uint32_t) * HDPATH_LEN_DEFAULT) { + THROW(APDU_CODE_WRONG_LENGTH); + } - MEMCPY(hdPath, G_io_apdu_buffer + offset, sizeof(uint32_t) * HDPATH_LEN_DEFAULT); + MEMCPY(hdPath, G_io_apdu_buffer + offset, + sizeof(uint32_t) * HDPATH_LEN_DEFAULT); - const bool mainnet = hdPath[0] == HDPATH_0_DEFAULT && - hdPath[1] == HDPATH_1_DEFAULT; + const bool mainnet = + hdPath[0] == HDPATH_0_DEFAULT && hdPath[1] == HDPATH_1_DEFAULT; - const bool testnet = hdPath[0] == HDPATH_0_TESTNET && - hdPath[1] == HDPATH_1_TESTNET; + const bool testnet = + hdPath[0] == HDPATH_0_TESTNET && hdPath[1] == HDPATH_1_TESTNET; - if (!mainnet && !testnet) { - THROW(APDU_CODE_DATA_INVALID); - } + if (!mainnet && !testnet) { + THROW(APDU_CODE_DATA_INVALID); + } } __Z_INLINE bool process_chunk(__Z_UNUSED volatile uint32_t *tx, uint32_t rx) { - const uint8_t payloadType = G_io_apdu_buffer[OFFSET_PAYLOAD_TYPE]; - - /* - if (G_io_apdu_buffer[OFFSET_P2] != 0 && G_io_apdu_buffer[OFFSET_P2] != 4 && G_io_apdu_buffer[OFFSET_P2] != 5 ) { - THROW(APDU_CODE_INVALIDP1P2); - } - */ - - if (rx < OFFSET_DATA) { - THROW(APDU_CODE_WRONG_LENGTH); - } - - uint32_t added; - switch (payloadType) - { - case 0: - tx_initialize(); - tx_reset(); - return false; - case 1: - added = tx_append(&(G_io_apdu_buffer[OFFSET_DATA]), rx - OFFSET_DATA); - if (added != rx - OFFSET_DATA) { - THROW(APDU_CODE_OUTPUT_BUFFER_TOO_SMALL); - } - return false; - case 2: - added = tx_append(&(G_io_apdu_buffer[OFFSET_DATA]), rx - OFFSET_DATA); - if (added != rx - OFFSET_DATA) { - THROW(APDU_CODE_OUTPUT_BUFFER_TOO_SMALL); - } - return true; - } - THROW(APDU_CODE_INVALIDP1P2); + const uint8_t payloadType = G_io_apdu_buffer[OFFSET_PAYLOAD_TYPE]; + + /* + if (G_io_apdu_buffer[OFFSET_P2] != 0 && G_io_apdu_buffer[OFFSET_P2] != 4 && + G_io_apdu_buffer[OFFSET_P2] != 5 ) { THROW(APDU_CODE_INVALIDP1P2); + } + */ + + if (rx < OFFSET_DATA) { + THROW(APDU_CODE_WRONG_LENGTH); + } + + uint32_t added; + switch (payloadType) { + case 0: + tx_initialize(); + tx_reset(); + return false; + case 1: + added = tx_append(&(G_io_apdu_buffer[OFFSET_DATA]), rx - OFFSET_DATA); + if (added != rx - OFFSET_DATA) { + THROW(APDU_CODE_OUTPUT_BUFFER_TOO_SMALL); + } + return false; + case 2: + added = tx_append(&(G_io_apdu_buffer[OFFSET_DATA]), rx - OFFSET_DATA); + if (added != rx - OFFSET_DATA) { + THROW(APDU_CODE_OUTPUT_BUFFER_TOO_SMALL); + } + return true; + } + THROW(APDU_CODE_INVALIDP1P2); } +__Z_INLINE void handleExtractSpendSignature(volatile uint32_t *tx, + uint32_t rx) { + zemu_log("----[handleExtractSpendSignature]\n"); -__Z_INLINE void handleExtractSpendSignature(volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleExtractSpendSignature]\n"); - - *tx = 0; - if (rx != APDU_MIN_LENGTH || G_io_apdu_buffer[OFFSET_DATA_LEN] != 0) { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + *tx = 0; + if (rx != APDU_MIN_LENGTH || G_io_apdu_buffer[OFFSET_DATA_LEN] != 0) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - zxerr_t err = crypto_extract_spend_signature(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2); + zxerr_t err = + crypto_extract_spend_signature(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2); - if (err == zxerr_ok) { - *tx = 64; - THROW(APDU_CODE_OK); - } else { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } + if (err == zxerr_ok) { + *tx = 64; + THROW(APDU_CODE_OK); + } else { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } } -__Z_INLINE void handleExtractTransparentSignature(volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleExtractTransparentSignature]\n"); +__Z_INLINE void handleExtractTransparentSignature(volatile uint32_t *tx, + uint32_t rx) { + zemu_log("----[handleExtractTransparentSignature]\n"); - *tx = 0; - if (rx != APDU_MIN_LENGTH || G_io_apdu_buffer[OFFSET_DATA_LEN] != 0) { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + *tx = 0; + if (rx != APDU_MIN_LENGTH || G_io_apdu_buffer[OFFSET_DATA_LEN] != 0) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - zxerr_t err = crypto_extract_transparent_signature(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2); + zxerr_t err = crypto_extract_transparent_signature(G_io_apdu_buffer, + IO_APDU_BUFFER_SIZE - 2); - if (err == zxerr_ok) { - *tx = 64; - THROW(APDU_CODE_OK); - } else { - view_idle_show(0, NULL); - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } + if (err == zxerr_ok) { + *tx = 64; + THROW(APDU_CODE_OK); + } else { + view_idle_show(0, NULL); + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } } __Z_INLINE void handleExtractSpendData(volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleExtractSpendData]\n"); + zemu_log("----[handleExtractSpendData]\n"); - *tx = 0; - if (rx != APDU_MIN_LENGTH || G_io_apdu_buffer[OFFSET_DATA_LEN] != 0) { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } - - zxerr_t err = crypto_extract_spend_proofkeyandrnd(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); - } + *tx = 0; + if (rx != APDU_MIN_LENGTH || G_io_apdu_buffer[OFFSET_DATA_LEN] != 0) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } + zxerr_t err = crypto_extract_spend_proofkeyandrnd(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); + } } __Z_INLINE void handleExtractOutputData(volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleExtractOutputData]\n"); + zemu_log("----[handleExtractOutputData]\n"); - *tx = 0; - if (rx != APDU_MIN_LENGTH || G_io_apdu_buffer[OFFSET_DATA_LEN] != 0) { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + *tx = 0; + if (rx != APDU_MIN_LENGTH || G_io_apdu_buffer[OFFSET_DATA_LEN] != 0) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - uint16_t replyLen = 0; - zxerr_t err = crypto_extract_output_rnd(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, &replyLen); - view_tx_state(); - if (err == zxerr_ok) { - *tx = replyLen; - THROW(APDU_CODE_OK); - } else { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } + uint16_t replyLen = 0; + zxerr_t err = crypto_extract_output_rnd(G_io_apdu_buffer, + IO_APDU_BUFFER_SIZE - 2, &replyLen); + view_tx_state(); + if (err == zxerr_ok) { + *tx = replyLen; + THROW(APDU_CODE_OK); + } else { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } } -__Z_INLINE void handleInitTX(volatile uint32_t *flags, - volatile uint32_t *tx, uint32_t rx) { - if (!process_chunk(tx, rx)) { - THROW(APDU_CODE_OK); - } +__Z_INLINE void handleInitTX(volatile uint32_t *flags, volatile uint32_t *tx, + uint32_t rx) { + if (!process_chunk(tx, rx)) { + THROW(APDU_CODE_OK); + } - zemu_log("----[handleInitTX]\n"); + zemu_log("----[handleInitTX]\n"); - *tx = 0; - const uint8_t *message = tx_get_buffer(); - const uint16_t messageLength = tx_get_buffer_length(); - - zxerr_t err = crypto_extracttx_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength); - if (err != zxerr_ok) { - transaction_reset(); - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - G_io_apdu_buffer[0] = err; - *tx = 1; - THROW(APDU_CODE_EXTRACT_TRANSACTION_FAIL); - } + *tx = 0; + const uint8_t *message = tx_get_buffer(); + const uint16_t messageLength = tx_get_buffer_length(); - err = crypto_hash_messagebuffer(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength); - if (err != zxerr_ok) { - transaction_reset(); - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - G_io_apdu_buffer[0] = err; - *tx = 1; - THROW(APDU_CODE_HASH_MSG_BUF_FAIL); - } + zxerr_t err = crypto_extracttx_sapling( + G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, message, messageLength); + if (err != zxerr_ok) { + transaction_reset(); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + G_io_apdu_buffer[0] = err; + *tx = 1; + THROW(APDU_CODE_EXTRACT_TRANSACTION_FAIL); + } + + err = crypto_hash_messagebuffer(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, + message, messageLength); + if (err != zxerr_ok) { + transaction_reset(); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + G_io_apdu_buffer[0] = err; + *tx = 1; + THROW(APDU_CODE_HASH_MSG_BUF_FAIL); + } -//////////// + //////////// - view_review_init(tx_getItem, tx_getNumItems, app_reply_hash); + view_review_init(tx_getItem, tx_getNumItems, app_reply_hash); - view_review_show(REVIEW_TXN); - *flags |= IO_ASYNCH_REPLY; + view_review_show(REVIEW_TXN); + *flags |= IO_ASYNCH_REPLY; } // Transmitted notes are stored on the blockchain in encrypted form. // If the note was sent to Alice, she uses her incoming viewing key (IVK) // to decrypt the note (so that she can subsequently send it). -// This function also returns the default diversifier to reduce interactions between host and device -__Z_INLINE void handleGetKeyIVK(volatile uint32_t *flags, - volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleGetKeyIVK]\n"); +// This function also returns the default diversifier to reduce interactions +// between host and device +__Z_INLINE void handleGetKeyIVK(volatile uint32_t *flags, volatile uint32_t *tx, + uint32_t rx) { + zemu_log("----[handleGetKeyIVK]\n"); + + *tx = 0; + if (rx < APDU_MIN_LENGTH || rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_IVK || + G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_IVK || + G_io_apdu_buffer[OFFSET_P1] == 0) { + zemu_log("Wrong length!\n"); + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } + uint32_t zip32path = 0; + parser_error_t prserr = parser_sapling_path(G_io_apdu_buffer + OFFSET_DATA, + DATA_LENGTH_GET_IVK, &zip32path); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + if (prserr != parser_ok) { *tx = 0; - if (rx < APDU_MIN_LENGTH || rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_IVK - || G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_IVK - || G_io_apdu_buffer[OFFSET_P1] == 0) { - zemu_log("Wrong length!\n"); - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } - - uint32_t zip32path = 0; - parser_error_t prserr = parser_sapling_path(G_io_apdu_buffer + OFFSET_DATA, DATA_LENGTH_GET_IVK, - &zip32path); - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - if (prserr != parser_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - key_state.kind = key_ivk; - uint16_t replyLen = 0; - - zxerr_t err = crypto_ivk_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, zip32path, &replyLen); - if (err != zxerr_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - key_state.len = (uint8_t) replyLen; + THROW(APDU_CODE_DATA_INVALID); + } + key_state.kind = key_ivk; + uint16_t replyLen = 0; + + zxerr_t err = crypto_ivk_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, + zip32path, &replyLen); + if (err != zxerr_ok) { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } + key_state.len = (uint8_t)replyLen; - view_review_init(key_getItem, key_getNumItems, app_reply_key); - view_review_show(REVIEW_TXN); - *flags |= IO_ASYNCH_REPLY; + view_review_init(key_getItem, key_getNumItems, app_reply_key); + view_review_show(REVIEW_TXN); + *flags |= IO_ASYNCH_REPLY; } // If Bob sends a note to Alice (stored on the blockchain in encrypted form), // he can decrypt using his outgoing viewing key (OVK). -__Z_INLINE void handleGetKeyOVK(volatile uint32_t *flags, - volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleGetKeyOVK]\n"); +__Z_INLINE void handleGetKeyOVK(volatile uint32_t *flags, volatile uint32_t *tx, + uint32_t rx) { + zemu_log("----[handleGetKeyOVK]\n"); + + *tx = 0; + if (rx < APDU_MIN_LENGTH || rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_OVK || + G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_OVK || + G_io_apdu_buffer[OFFSET_P1] == 0) { + zemu_log("Wrong length!\n"); + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } + uint32_t zip32path = 0; + parser_error_t prserr = parser_sapling_path(G_io_apdu_buffer + OFFSET_DATA, + DATA_LENGTH_GET_OVK, &zip32path); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + if (prserr != parser_ok) { *tx = 0; - if (rx < APDU_MIN_LENGTH || rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_OVK - || G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_OVK - || G_io_apdu_buffer[OFFSET_P1] == 0) { - zemu_log("Wrong length!\n"); - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } - - uint32_t zip32path = 0; - parser_error_t prserr = parser_sapling_path(G_io_apdu_buffer + OFFSET_DATA, DATA_LENGTH_GET_OVK, - &zip32path); - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - if (prserr != parser_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - key_state.kind = key_ovk; - uint16_t replyLen = 0; - - zxerr_t err = crypto_ovk_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, zip32path, &replyLen); - if (err != zxerr_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - key_state.len = (uint8_t) replyLen; + THROW(APDU_CODE_DATA_INVALID); + } + key_state.kind = key_ovk; + uint16_t replyLen = 0; + + zxerr_t err = crypto_ovk_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, + zip32path, &replyLen); + if (err != zxerr_ok) { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } + key_state.len = (uint8_t)replyLen; - view_review_init(key_getItem, key_getNumItems, app_reply_key); - view_review_show(REVIEW_TXN); - *flags |= IO_ASYNCH_REPLY; + view_review_init(key_getItem, key_getNumItems, app_reply_key); + view_review_show(REVIEW_TXN); + *flags |= IO_ASYNCH_REPLY; } - // Get the sapling full viewing key (ak, nk, ovk) -__Z_INLINE void handleGetKeyFVK(volatile uint32_t *flags, - volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleGetKeyFVK]\n"); +__Z_INLINE void handleGetKeyFVK(volatile uint32_t *flags, volatile uint32_t *tx, + uint32_t rx) { + zemu_log("----[handleGetKeyFVK]\n"); + + *tx = 0; + if (rx < APDU_MIN_LENGTH || rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_FVK || + G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_FVK || + G_io_apdu_buffer[OFFSET_P1] == 0) { + zemu_log("Wrong length!\n"); + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } + uint32_t zip32path = 0; + parser_error_t prserr = parser_sapling_path(G_io_apdu_buffer + OFFSET_DATA, + DATA_LENGTH_GET_FVK, &zip32path); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + if (prserr != parser_ok) { *tx = 0; - if (rx < APDU_MIN_LENGTH || rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_FVK - || G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_FVK - || G_io_apdu_buffer[OFFSET_P1] == 0) { - zemu_log("Wrong length!\n"); - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } - - uint32_t zip32path = 0; - parser_error_t prserr = parser_sapling_path(G_io_apdu_buffer + OFFSET_DATA, DATA_LENGTH_GET_FVK, - &zip32path); - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - if (prserr != parser_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - key_state.kind = key_fvk; - uint16_t replyLen = 0; - - zxerr_t err = crypto_fvk_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, zip32path, &replyLen); - if (err != zxerr_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - key_state.len = (uint8_t) replyLen; + THROW(APDU_CODE_DATA_INVALID); + } + key_state.kind = key_fvk; + uint16_t replyLen = 0; + + zxerr_t err = crypto_fvk_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, + zip32path, &replyLen); + if (err != zxerr_ok) { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } + key_state.len = (uint8_t)replyLen; - view_review_init(key_getItem, key_getNumItems, app_reply_key); - view_review_show(REVIEW_TXN); - *flags |= IO_ASYNCH_REPLY; + view_review_init(key_getItem, key_getNumItems, app_reply_key); + view_review_show(REVIEW_TXN); + *flags |= IO_ASYNCH_REPLY; } // Computing the note nullifier nf is required in order to spend the note. @@ -349,557 +359,566 @@ __Z_INLINE void handleGetKeyFVK(volatile uint32_t *flags, // and the note position pos. // (nk is part of the full viewing key fvk = (ak, nk, ovk) ) __Z_INLINE void handleGetNullifier(volatile uint32_t *flags, - volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleGetNullifier]\n"); - - *tx = 0; - if (rx < APDU_MIN_LENGTH || rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_NF - || G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_NF - || G_io_apdu_buffer[OFFSET_P1] == 0) { - zemu_log("Wrong length!\n"); - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } - - uint32_t zip32path = 0; - parser_error_t prserr = parser_sapling_path(G_io_apdu_buffer + OFFSET_DATA, DATA_LENGTH_GET_NF, - &zip32path); - if (prserr != parser_ok) { - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - *tx = 0; - zemu_log("Failed to get seed!\n"); - THROW(APDU_CODE_DATA_INVALID); - } - - // get note position from payload - uint64_t notepos = 0; - memcpy(¬epos, G_io_apdu_buffer + OFFSET_DATA + ZIP32_PATH_SIZE, - NOTE_POSITION_SIZE); - - // get note commitment from payload - uint8_t cm[NOTE_COMMITMENT_SIZE] = {0}; - memcpy(cm, G_io_apdu_buffer + OFFSET_DATA + ZIP32_PATH_SIZE + NOTE_POSITION_SIZE, - NOTE_COMMITMENT_SIZE); + volatile uint32_t *tx, uint32_t rx) { + zemu_log("----[handleGetNullifier]\n"); + + *tx = 0; + if (rx < APDU_MIN_LENGTH || rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_NF || + G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_NF || + G_io_apdu_buffer[OFFSET_P1] == 0) { + zemu_log("Wrong length!\n"); + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } + uint32_t zip32path = 0; + parser_error_t prserr = parser_sapling_path(G_io_apdu_buffer + OFFSET_DATA, + DATA_LENGTH_GET_NF, &zip32path); + if (prserr != parser_ok) { MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + *tx = 0; + zemu_log("Failed to get seed!\n"); + THROW(APDU_CODE_DATA_INVALID); + } + + // get note position from payload + uint64_t notepos = 0; + memcpy(¬epos, G_io_apdu_buffer + OFFSET_DATA + ZIP32_PATH_SIZE, + NOTE_POSITION_SIZE); + + // get note commitment from payload + uint8_t cm[NOTE_COMMITMENT_SIZE] = {0}; + memcpy(cm, + G_io_apdu_buffer + OFFSET_DATA + ZIP32_PATH_SIZE + NOTE_POSITION_SIZE, + NOTE_COMMITMENT_SIZE); + + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + + key_state.kind = nf; + uint16_t replyLen = 0; + + // this needs to get Full viewing key = (ak, nk, ovk) and note position, to + // then compute nullifier G_io_apdu_buffer contains zip32path, note position, + // note commitment + zxerr_t err = crypto_nullifier_sapling( + G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, notepos, cm, &replyLen); + if (err != zxerr_ok) { + zemu_log("Failed to get nullifier!\n"); + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } + key_state.len = (uint8_t)replyLen; - key_state.kind = nf; - uint16_t replyLen = 0; - - // this needs to get Full viewing key = (ak, nk, ovk) and note position, to then compute nullifier - // G_io_apdu_buffer contains zip32path, note position, note commitment - zxerr_t err = crypto_nullifier_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, notepos, - cm, &replyLen); - if (err != zxerr_ok) { - zemu_log("Failed to get nullifier!\n"); - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - key_state.len = (uint8_t) replyLen; - - view_review_init(key_getItem, key_getNumItems, app_reply_key); - view_review_show(REVIEW_TXN); - *flags |= IO_ASYNCH_REPLY; + view_review_init(key_getItem, key_getNumItems, app_reply_key); + view_review_show(REVIEW_TXN); + *flags |= IO_ASYNCH_REPLY; } __Z_INLINE void handleCheckandSign(volatile uint32_t *tx, uint32_t rx) { - if (!process_chunk(tx, rx)) { - THROW(APDU_CODE_OK); - } - *tx = 0; - - zemu_log("----[handleCheckandSign]\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]; - snprintf(buffer, sizeof(buffer), "Tx Version is %d", txVersion); - zemu_log_stack(buffer); - - if (!((txVersion == TX_VERSION_SAPLING) || (txVersion == TX_VERSION_NU5))) - { - zemu_log("Unhandled tx version\n"); - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - view_idle_show(0, NULL); - transaction_reset(); - THROW(APDU_CODE_UNHANDLED_TX_VERSION); - } - - if (get_state() != STATE_PROCESSED_ALL_EXTRACTIONS) { - zemu_log("[handleCheckandSign] not STATE_PROCESSED_ALL_EXTRACTIONS\n"); - 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, txVersion); - 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, txVersion); - 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, txVersion); - 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); - } + if (!process_chunk(tx, rx)) { + THROW(APDU_CODE_OK); + } + *tx = 0; - err = crypto_check_joinsplits(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_JOINSPLIT_INVALID); - } + zemu_log("----[handleCheckandSign]\n"); - // /!\ the valuebalance is different to the total value - 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); - } + const uint8_t *message = tx_get_buffer(); + const uint16_t messageLength = tx_get_buffer_length(); - 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); - } + const uint8_t txVersion = G_io_apdu_buffer[OFFSET_P2]; - 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); - } + char buffer[20]; + snprintf(buffer, sizeof(buffer), "Tx Version is %d", txVersion); + zemu_log_stack(buffer); - set_state(STATE_VERIFIED_ALL_TXDATA); - view_tx_state(); + if (!((txVersion == TX_VERSION_SAPLING) || (txVersion == TX_VERSION_NU5))) { + zemu_log("Unhandled tx version\n"); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + view_idle_show(0, NULL); + transaction_reset(); + THROW(APDU_CODE_UNHANDLED_TX_VERSION); + } - 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); - } + if (get_state() != STATE_PROCESSED_ALL_EXTRACTIONS) { + zemu_log("[handleCheckandSign] not STATE_PROCESSED_ALL_EXTRACTIONS\n"); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + view_idle_show(0, NULL); + transaction_reset(); + THROW(APDU_CODE_UNPROCESSED_TX); + } - 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); - } + set_state(STATE_CHECKING_ALL_TXDATA); + view_tx_state(); - 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); - } + zxerr_t err = crypto_check_prevouts(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_PREVOUT_INVALID); + } + + err = crypto_check_sequence(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_SEQUENCE_INVALID); + } + + err = crypto_check_outputs(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_OUTPUTS_INVALID); + } + + err = crypto_check_joinsplits(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_JOINSPLIT_INVALID); + } + + // /!\ the valuebalance is different to the total value + 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(); + set_state(STATE_SIGNED_TX); + view_tx_state(); - *tx = 32; - THROW(APDU_CODE_OK); + *tx = 32; + THROW(APDU_CODE_OK); } __Z_INLINE void handleGetAddrSecp256K1(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleGetAddrSecp256K1]\n"); + zemu_log("----[handleGetAddrSecp256K1]\n"); - extractHDPath(rx, OFFSET_DATA); - *tx = 0; - uint8_t requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; - uint16_t replyLen = 0; + extractHDPath(rx, OFFSET_DATA); + *tx = 0; + uint8_t requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; + uint16_t replyLen = 0; - zxerr_t err = crypto_fillAddress_secp256k1(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, &replyLen); - if (err != zxerr_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } + zxerr_t err = crypto_fillAddress_secp256k1( + G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, &replyLen); + if (err != zxerr_ok) { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } - action_addrResponse.kind = addr_secp256k1; - action_addrResponse.len = replyLen; + action_addrResponse.kind = addr_secp256k1; + action_addrResponse.len = replyLen; - if (requireConfirmation) { - view_review_init(addr_getItem, addr_getNumItems, app_reply_address); - view_review_show(REVIEW_ADDRESS); - *flags |= IO_ASYNCH_REPLY; - return; - } - *tx = replyLen; - THROW(APDU_CODE_OK); + if (requireConfirmation) { + view_review_init(addr_getItem, addr_getNumItems, app_reply_address); + view_review_show(REVIEW_ADDRESS); + *flags |= IO_ASYNCH_REPLY; + return; + } + *tx = replyLen; + THROW(APDU_CODE_OK); } - __Z_INLINE void handleGetAddrSaplingDiv(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleGetAddrSaplingDiv]\n"); + zemu_log("----[handleGetAddrSaplingDiv]\n"); - *tx = 0; - if (rx < APDU_MIN_LENGTH) { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + *tx = 0; + if (rx < APDU_MIN_LENGTH) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - if (rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_ADDR_DIV) { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + if (rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_ADDR_DIV) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - if (G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_ADDR_DIV) { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + if (G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_ADDR_DIV) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - uint8_t requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; + uint8_t requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; - uint16_t replyLen = 0; + uint16_t replyLen = 0; - zemu_log_stack("handleGetAddrSapling_withdiv"); + zemu_log_stack("handleGetAddrSapling_withdiv"); - parser_addr_div_t parser_addr; - MEMZERO(&parser_addr, sizeof(parser_addr_div_t)); + parser_addr_div_t parser_addr; + MEMZERO(&parser_addr, sizeof(parser_addr_div_t)); - parser_error_t prserr = parser_sapling_path_with_div(G_io_apdu_buffer + OFFSET_DATA, DATA_LENGTH_GET_ADDR_DIV, - &parser_addr); - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - if (prserr != parser_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - zxerr_t err = crypto_fillAddress_with_diversifier_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, - parser_addr.path, parser_addr.div, &replyLen); - if (err != zxerr_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - action_addrResponse.kind = addr_sapling_div; - action_addrResponse.len = replyLen; - - if (requireConfirmation) { - view_review_init(addr_getItem, addr_getNumItems, app_reply_address); - view_review_show(REVIEW_ADDRESS); - *flags |= IO_ASYNCH_REPLY; - return; - } - *tx = replyLen; - THROW(APDU_CODE_OK); + parser_error_t prserr = parser_sapling_path_with_div( + G_io_apdu_buffer + OFFSET_DATA, DATA_LENGTH_GET_ADDR_DIV, &parser_addr); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + if (prserr != parser_ok) { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } + zxerr_t err = crypto_fillAddress_with_diversifier_sapling( + G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, parser_addr.path, + parser_addr.div, &replyLen); + if (err != zxerr_ok) { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } + action_addrResponse.kind = addr_sapling_div; + action_addrResponse.len = replyLen; + + if (requireConfirmation) { + view_review_init(addr_getItem, addr_getNumItems, app_reply_address); + view_review_show(REVIEW_ADDRESS); + *flags |= IO_ASYNCH_REPLY; + return; + } + *tx = replyLen; + THROW(APDU_CODE_OK); } __Z_INLINE void handleGetDiversifierList(volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleGetDiversifierList]\n"); + zemu_log("----[handleGetDiversifierList]\n"); - *tx = 0; - if (rx < APDU_MIN_LENGTH) { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + *tx = 0; + if (rx < APDU_MIN_LENGTH) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - if (rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_DIV_LIST) { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + if (rx - APDU_MIN_LENGTH != DATA_LENGTH_GET_DIV_LIST) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - if (G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_DIV_LIST) { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + if (G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_DIV_LIST) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - uint16_t replyLen = 0; + uint16_t replyLen = 0; - zemu_log_stack("handleGetDiversifierList"); + zemu_log_stack("handleGetDiversifierList"); - parser_addr_div_t parser_addr; - MEMZERO(&parser_addr, sizeof(parser_addr_div_t)); + parser_addr_div_t parser_addr; + MEMZERO(&parser_addr, sizeof(parser_addr_div_t)); - parser_error_t prserr = parser_sapling_path_with_div(G_io_apdu_buffer + OFFSET_DATA, DATA_LENGTH_GET_DIV_LIST, - &parser_addr); - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - if (prserr != parser_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - zxerr_t err = crypto_diversifier_with_startindex(G_io_apdu_buffer, parser_addr.path, parser_addr.div, &replyLen); + parser_error_t prserr = parser_sapling_path_with_div( + G_io_apdu_buffer + OFFSET_DATA, DATA_LENGTH_GET_DIV_LIST, &parser_addr); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + if (prserr != parser_ok) { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } + zxerr_t err = crypto_diversifier_with_startindex( + G_io_apdu_buffer, parser_addr.path, parser_addr.div, &replyLen); - if (err == zxerr_ok) { - *tx = replyLen; - THROW(APDU_CODE_OK); - } else { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } + if (err == zxerr_ok) { + *tx = replyLen; + THROW(APDU_CODE_OK); + } else { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } } __Z_INLINE void handleGetAddrSapling(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { - zemu_log("----[handleGetAddrSapling]\n"); - - *tx = 0; - if (rx < APDU_MIN_LENGTH) { - zemu_log("Missing data!\n"); - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + zemu_log("----[handleGetAddrSapling]\n"); + *tx = 0; + if (rx < APDU_MIN_LENGTH) { + zemu_log("Missing data!\n"); + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - if ( rx != (uint32_t)(DATA_LENGTH_GET_ADDR_SAPLING + APDU_MIN_LENGTH)) { - zemu_log("Wrong length!\n"); - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + if (rx != (uint32_t)(DATA_LENGTH_GET_ADDR_SAPLING + APDU_MIN_LENGTH)) { + zemu_log("Wrong length!\n"); + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - if (G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_ADDR_SAPLING) { - zemu_log("Wrong offset data length!\n"); - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); - } + if (G_io_apdu_buffer[OFFSET_DATA_LEN] != DATA_LENGTH_GET_ADDR_SAPLING) { + zemu_log("Wrong offset data length!\n"); + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } - uint8_t requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; + uint8_t requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; - uint32_t zip32path = 0; - parser_error_t prserr = parser_sapling_path(G_io_apdu_buffer + OFFSET_DATA, DATA_LENGTH_GET_ADDR_SAPLING, - &zip32path); - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - if (prserr != parser_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - uint16_t replyLen = 0; - zxerr_t err = crypto_fillAddress_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, zip32path, &replyLen); - if (err != zxerr_ok) { - *tx = 0; - THROW(APDU_CODE_DATA_INVALID); - } - action_addrResponse.kind = addr_sapling; - action_addrResponse.len = replyLen; - - if (requireConfirmation) { - view_review_init(addr_getItem, addr_getNumItems, app_reply_address); - view_review_show(REVIEW_ADDRESS); - *flags |= IO_ASYNCH_REPLY; - return; - } + uint32_t zip32path = 0; + parser_error_t prserr = parser_sapling_path( + G_io_apdu_buffer + OFFSET_DATA, DATA_LENGTH_GET_ADDR_SAPLING, &zip32path); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + if (prserr != parser_ok) { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } + uint16_t replyLen = 0; + zxerr_t err = crypto_fillAddress_sapling( + G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, zip32path, &replyLen); + if (err != zxerr_ok) { + *tx = 0; + THROW(APDU_CODE_DATA_INVALID); + } + action_addrResponse.kind = addr_sapling; + action_addrResponse.len = replyLen; + + if (requireConfirmation) { + view_review_init(addr_getItem, addr_getNumItems, app_reply_address); + view_review_show(REVIEW_ADDRESS); + *flags |= IO_ASYNCH_REPLY; + return; + } - *tx = replyLen; - THROW(APDU_CODE_OK); + *tx = replyLen; + THROW(APDU_CODE_OK); } -__Z_INLINE void handleSignSapling() { - THROW(APDU_CODE_COMMAND_NOT_ALLOWED); -} +__Z_INLINE void handleSignSapling() { THROW(APDU_CODE_COMMAND_NOT_ALLOWED); } #if defined(APP_TESTING) -#include #include "cx.h" -#include "rslib.h" #include "jubjub.h" +#include "rslib.h" +#include void handleTest(volatile uint32_t *tx) { - uint8_t point[32] = { 48, 181, 242, 170, 173, 50, 86, 48, 188, 221, 219, 206, 77, 103, 101, 109, 5, 253, 28, 194, - 208, 55, 187, 83, 117, 182, 233, 109, 158, 1, 161, 215}; + uint8_t point[32] = {48, 181, 242, 170, 173, 50, 86, 48, 188, 221, 219, + 206, 77, 103, 101, 109, 5, 253, 28, 194, 208, 55, + 187, 83, 117, 182, 233, 109, 158, 1, 161, 215}; - uint8_t scalar[32] = { 0x66, 0x5e, 0xd6, 0xf7, 0xb7, 0x93, 0xaf, 0xa1, 0x82, 0x21, 0xe1, 0x57, 0xba, 0xd5, - 0x43, 0x3c, 0x54, 0x23, 0xf4, 0xfe, 0xc9, 0x46, 0xe0, 0x8e, 0xd6, 0x30, 0xa0, 0xc6, - 0x0a, 0x1f, 0xac, 0x02,}; + uint8_t scalar[32] = { + 0x66, 0x5e, 0xd6, 0xf7, 0xb7, 0x93, 0xaf, 0xa1, 0x82, 0x21, 0xe1, + 0x57, 0xba, 0xd5, 0x43, 0x3c, 0x54, 0x23, 0xf4, 0xfe, 0xc9, 0x46, + 0xe0, 0x8e, 0xd6, 0x30, 0xa0, 0xc6, 0x0a, 0x1f, 0xac, 0x02, + }; - jubjub_extendedpoint p; - jubjub_fq scal; - jubjub_field_frombytes(scal,scalar); - - jubjub_extendedpoint_tobytes(point,JUBJUB_GEN); - zxerr_t err = jubjub_extendedpoint_frombytes(&p, point); - if(err!=zxerr_ok){ - *tx = 0; - MEMZERO(point, 32); - THROW(APDU_CODE_OK); - } - //MEMCPY(&p, &JUBJUB_GEN, 32); - //jubjub_extendedpoint_scalarmult(&p, scal); - jubjub_extendedpoint_tobytes(point,p); + jubjub_extendedpoint p; + jubjub_fq scal; + jubjub_field_frombytes(scal, scalar); - MEMCPY(G_io_apdu_buffer, point,32); - *tx = 32; + jubjub_extendedpoint_tobytes(point, JUBJUB_GEN); + zxerr_t err = jubjub_extendedpoint_frombytes(&p, point); + if (err != zxerr_ok) { + *tx = 0; + MEMZERO(point, 32); THROW(APDU_CODE_OK); + } + // MEMCPY(&p, &JUBJUB_GEN, 32); + // jubjub_extendedpoint_scalarmult(&p, scal); + jubjub_extendedpoint_tobytes(point, p); + + MEMCPY(G_io_apdu_buffer, point, 32); + *tx = 32; + THROW(APDU_CODE_OK); } #endif void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { - uint16_t sw = 0; - - BEGIN_TRY - { - TRY - { - if (G_io_apdu_buffer[OFFSET_CLA] != CLA) { - THROW(APDU_CODE_CLA_NOT_SUPPORTED); - } - - if (rx < APDU_MIN_LENGTH) { - THROW(APDU_CODE_WRONG_LENGTH); - } - - switch (G_io_apdu_buffer[OFFSET_INS]) { - case INS_GET_VERSION: { - handle_getversion(tx); - break; - } - - case INS_GET_ADDR_SECP256K1: { - CHECK_PIN_VALIDATED() - handleGetAddrSecp256K1(flags, tx, rx); - break; - } - - case INS_GET_IVK: { - CHECK_PIN_VALIDATED() - handleGetKeyIVK(flags, tx, rx); - break; - } - - case INS_GET_OVK: { - CHECK_PIN_VALIDATED() - handleGetKeyOVK(flags, tx, rx); - break; - } - - case INS_GET_NF: { - CHECK_PIN_VALIDATED() - handleGetNullifier(flags, tx, rx); - break; - } - - case INS_GET_FVK: { - zemu_log("----[INS_GET_FVK]\n"); - CHECK_PIN_VALIDATED() - handleGetKeyFVK(flags, tx, rx); - break; - } - - case INS_INIT_TX: { - CHECK_PIN_VALIDATED() - handleInitTX(flags, tx, rx); - break; - } - - case INS_EXTRACT_SPEND: { - CHECK_PIN_VALIDATED() - handleExtractSpendData(tx, rx); - break; - } - - case INS_EXTRACT_OUTPUT: { - CHECK_PIN_VALIDATED() - handleExtractOutputData(tx, rx); - break; - } - - case INS_CHECKANDSIGN: { - CHECK_PIN_VALIDATED() - handleCheckandSign(tx, rx); - break; - } - - case INS_EXTRACT_SPENDSIG: { - CHECK_PIN_VALIDATED() - handleExtractSpendSignature(tx, rx); - break; - } - - case INS_EXTRACT_TRANSSIG: { - CHECK_PIN_VALIDATED() - handleExtractTransparentSignature(tx, rx); - break; - } - - case INS_GET_ADDR_SAPLING: { - CHECK_PIN_VALIDATED() - handleGetAddrSapling(flags, tx, rx); - break; - } - - case INS_GET_DIV_LIST: { - CHECK_PIN_VALIDATED() - handleGetDiversifierList(tx, rx); - break; - } - - case INS_GET_ADDR_SAPLING_DIV: { - CHECK_PIN_VALIDATED() - handleGetAddrSaplingDiv(flags, tx, rx); - break; - } - - case INS_SIGN_SAPLING: { - CHECK_PIN_VALIDATED() - handleSignSapling(); - break; - } + uint16_t sw = 0; + + BEGIN_TRY { + TRY { + if (G_io_apdu_buffer[OFFSET_CLA] != CLA) { + THROW(APDU_CODE_CLA_NOT_SUPPORTED); + } + + if (rx < APDU_MIN_LENGTH) { + THROW(APDU_CODE_WRONG_LENGTH); + } + + switch (G_io_apdu_buffer[OFFSET_INS]) { + case INS_GET_VERSION: { + handle_getversion(tx); + break; + } + + case INS_GET_ADDR_SECP256K1: { + CHECK_PIN_VALIDATED() + handleGetAddrSecp256K1(flags, tx, rx); + break; + } + + case INS_GET_IVK: { + CHECK_PIN_VALIDATED() + handleGetKeyIVK(flags, tx, rx); + break; + } + + case INS_GET_OVK: { + CHECK_PIN_VALIDATED() + handleGetKeyOVK(flags, tx, rx); + break; + } + + case INS_GET_NF: { + CHECK_PIN_VALIDATED() + handleGetNullifier(flags, tx, rx); + break; + } + + case INS_GET_FVK: { + zemu_log("----[INS_GET_FVK]\n"); + CHECK_PIN_VALIDATED() + handleGetKeyFVK(flags, tx, rx); + break; + } + + case INS_INIT_TX: { + CHECK_PIN_VALIDATED() + handleInitTX(flags, tx, rx); + break; + } + + case INS_EXTRACT_SPEND: { + CHECK_PIN_VALIDATED() + handleExtractSpendData(tx, rx); + break; + } + + case INS_EXTRACT_OUTPUT: { + CHECK_PIN_VALIDATED() + handleExtractOutputData(tx, rx); + break; + } + + case INS_CHECKANDSIGN: { + CHECK_PIN_VALIDATED() + handleCheckandSign(tx, rx); + break; + } + + case INS_EXTRACT_SPENDSIG: { + CHECK_PIN_VALIDATED() + handleExtractSpendSignature(tx, rx); + break; + } + + case INS_EXTRACT_TRANSSIG: { + CHECK_PIN_VALIDATED() + handleExtractTransparentSignature(tx, rx); + break; + } + + case INS_GET_ADDR_SAPLING: { + CHECK_PIN_VALIDATED() + handleGetAddrSapling(flags, tx, rx); + break; + } + + case INS_GET_DIV_LIST: { + CHECK_PIN_VALIDATED() + handleGetDiversifierList(tx, rx); + break; + } + + case INS_GET_ADDR_SAPLING_DIV: { + CHECK_PIN_VALIDATED() + handleGetAddrSaplingDiv(flags, tx, rx); + break; + } + + case INS_SIGN_SAPLING: { + CHECK_PIN_VALIDATED() + handleSignSapling(); + break; + } #if defined(APP_TESTING) - case INS_TEST: { - handleTest(tx); - /* - G_io_apdu_buffer[0] = 0xCA; - G_io_apdu_buffer[1] = 0xFE; - *tx = 3; - */ - THROW(APDU_CODE_OK); - break; - } + case INS_TEST: { + handleTest(tx); + /* + G_io_apdu_buffer[0] = 0xCA; + G_io_apdu_buffer[1] = 0xFE; + *tx = 3; + */ + THROW(APDU_CODE_OK); + break; + } #endif - default: - THROW(APDU_CODE_INS_NOT_SUPPORTED); - } - } - CATCH(EXCEPTION_IO_RESET) { - THROW(EXCEPTION_IO_RESET); - } - CATCH_OTHER(e) - { - switch (e & 0xF000) { - case 0x6000: - case APDU_CODE_OK: - sw = e; - break; - default: - sw = 0x6800 | (e & 0x7FF); - break; - } - G_io_apdu_buffer[*tx] = sw >> 8; - G_io_apdu_buffer[*tx + 1] = sw; - *tx += 2; - } - FINALLY - { - } - } - END_TRY; + default: + THROW(APDU_CODE_INS_NOT_SUPPORTED); + } + } + CATCH(EXCEPTION_IO_RESET) { THROW(EXCEPTION_IO_RESET); } + CATCH_OTHER(e) { + switch (e & 0xF000) { + case 0x6000: + case APDU_CODE_OK: + sw = e; + break; + default: + sw = 0x6800 | (e & 0x7FF); + break; + } + G_io_apdu_buffer[*tx] = sw >> 8; + G_io_apdu_buffer[*tx + 1] = sw; + *tx += 2; + } + FINALLY {} + } + END_TRY; } diff --git a/app/src/c_api/rust.c b/app/src/c_api/rust.c index b779699e..046ca3e5 100644 --- a/app/src/c_api/rust.c +++ b/app/src/c_api/rust.c @@ -1,12 +1,12 @@ -#include -#include -#include -#include -#include "os.h" -#include "cx.h" #include "aes.h" #include "coin.h" +#include "cx.h" #include "jubjub.h" +#include "os.h" +#include +#include +#include +#include #define CTX_REDJUBJUB "Zcash_RedJubjubH" #define CTX_REDJUBJUB_LEN 16 @@ -20,53 +20,60 @@ #include #include -#if defined (TARGET_NANOS) || defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX) +#if defined(TARGET_NANOS) || defined(TARGET_NANOX) || \ + defined(TARGET_NANOS2) || defined(TARGET_STAX) #include "lcx_rng.h" unsigned char *bolos_cx_rng(uint8_t *buffer, size_t len) { - cx_rng_no_throw(buffer, len); - return buffer; + cx_rng_no_throw(buffer, len); + return buffer; } #endif -void c_blake2b32_withpersonal(const uint8_t *person, const uint8_t *a, uint32_t a_len, uint8_t *out) { - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) person, 16); - cx_hash_no_throw(&ctx.header, CX_LAST, a, a_len, out, 256); +void c_blake2b32_withpersonal(const uint8_t *person, const uint8_t *a, + uint32_t a_len, uint8_t *out) { + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)person, 16); + cx_hash_no_throw(&ctx.header, CX_LAST, a, a_len, out, 256); }; -void c_blake2b64_withpersonal(const uint8_t *person, const uint8_t *a, uint32_t a_len, uint8_t *out) { - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 512, NULL, 0, (uint8_t *) person, 16); - cx_hash_no_throw(&ctx.header, CX_LAST, a, a_len, out, 512); +void c_blake2b64_withpersonal(const uint8_t *person, const uint8_t *a, + uint32_t a_len, uint8_t *out) { + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw(&ctx, 512, NULL, 0, (uint8_t *)person, 16); + cx_hash_no_throw(&ctx.header, CX_LAST, a, a_len, out, 512); }; void c_zcash_blake2b_redjubjub(const uint8_t *a, uint32_t a_len, - const uint8_t *b, uint32_t b_len, - uint8_t *out) { - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 8 * CTX_REDJUBJUB_HASH_LEN, NULL, 0, (uint8_t *) CTX_REDJUBJUB, CTX_REDJUBJUB_LEN); - cx_hash_no_throw(&ctx.header, 0, a, a_len, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, b, b_len, out, CTX_REDJUBJUB_HASH_LEN); + const uint8_t *b, uint32_t b_len, uint8_t *out) { + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw(&ctx, 8 * CTX_REDJUBJUB_HASH_LEN, NULL, 0, + (uint8_t *)CTX_REDJUBJUB, CTX_REDJUBJUB_LEN); + cx_hash_no_throw(&ctx.header, 0, a, a_len, NULL, 0); + cx_hash_no_throw(&ctx.header, CX_LAST, b, b_len, out, CTX_REDJUBJUB_HASH_LEN); } void c_zcash_blake2b_expand_seed(const uint8_t *a, uint32_t a_len, const uint8_t *b, uint32_t b_len, uint8_t *out) { - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 8 * CTX_EXPAND_SEED_HASH_LEN, NULL, 0, (uint8_t *) CTX_EXPAND_SEED, CTX_EXPAND_SEED_LEN); - cx_hash_no_throw(&ctx.header, 0, a, a_len, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, b, b_len, out, CTX_EXPAND_SEED_HASH_LEN); + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw(&ctx, 8 * CTX_EXPAND_SEED_HASH_LEN, NULL, 0, + (uint8_t *)CTX_EXPAND_SEED, CTX_EXPAND_SEED_LEN); + cx_hash_no_throw(&ctx.header, 0, a, a_len, NULL, 0); + cx_hash_no_throw(&ctx.header, CX_LAST, b, b_len, out, + CTX_EXPAND_SEED_HASH_LEN); } void c_zcash_blake2b_expand_vec_two(const uint8_t *a, uint32_t a_len, const uint8_t *b, uint32_t b_len, const uint8_t *c, uint32_t c_len, uint8_t *out) { - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 8 * CTX_EXPAND_SEED_HASH_LEN, NULL, 0, (uint8_t *) CTX_EXPAND_SEED, CTX_EXPAND_SEED_LEN); - cx_hash_no_throw(&ctx.header, 0, a, a_len, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, b, b_len, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, c, c_len, out, CTX_EXPAND_SEED_HASH_LEN); + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw(&ctx, 8 * CTX_EXPAND_SEED_HASH_LEN, NULL, 0, + (uint8_t *)CTX_EXPAND_SEED, CTX_EXPAND_SEED_LEN); + cx_hash_no_throw(&ctx.header, 0, a, a_len, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, b, b_len, NULL, 0); + cx_hash_no_throw(&ctx.header, CX_LAST, c, c_len, out, + CTX_EXPAND_SEED_HASH_LEN); } void c_zcash_blake2b_expand_vec_four(const uint8_t *a, uint32_t a_len, @@ -75,111 +82,114 @@ void c_zcash_blake2b_expand_vec_four(const uint8_t *a, uint32_t a_len, const uint8_t *d, uint32_t d_len, const uint8_t *e, uint32_t e_len, uint8_t *out) { - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 8 * CTX_EXPAND_SEED_HASH_LEN, NULL, 0, (uint8_t *) CTX_EXPAND_SEED, CTX_EXPAND_SEED_LEN); - cx_hash_no_throw(&ctx.header, 0, a, a_len, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, b, b_len, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, c, c_len, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, d, d_len, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, e, e_len, out, CTX_EXPAND_SEED_HASH_LEN); + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw(&ctx, 8 * CTX_EXPAND_SEED_HASH_LEN, NULL, 0, + (uint8_t *)CTX_EXPAND_SEED, CTX_EXPAND_SEED_LEN); + cx_hash_no_throw(&ctx.header, 0, a, a_len, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, b, b_len, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, c, c_len, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, d, d_len, NULL, 0); + cx_hash_no_throw(&ctx.header, CX_LAST, e, e_len, out, + CTX_EXPAND_SEED_HASH_LEN); } -void zcash_blake2b_hash_two( - const uint8_t *perso, uint32_t perso_len, - const uint8_t *a, uint32_t a_len, - const uint8_t *b, uint32_t b_len, - uint8_t *out, uint32_t out_len) { - cx_blake2b_t zcashHashBlake2b; - cx_blake2b_init2_no_throw(&zcashHashBlake2b, 8 * out_len, NULL, 0, (uint8_t *) perso, perso_len); - cx_hash_no_throw(&zcashHashBlake2b.header, 0, a, a_len, NULL, 0); - cx_hash_no_throw(&zcashHashBlake2b.header, CX_LAST, b, b_len, out, out_len); +void zcash_blake2b_hash_two(const uint8_t *perso, uint32_t perso_len, + const uint8_t *a, uint32_t a_len, const uint8_t *b, + uint32_t b_len, uint8_t *out, uint32_t out_len) { + cx_blake2b_t zcashHashBlake2b; + cx_blake2b_init2_no_throw(&zcashHashBlake2b, 8 * out_len, NULL, 0, + (uint8_t *)perso, perso_len); + cx_hash_no_throw(&zcashHashBlake2b.header, 0, a, a_len, NULL, 0); + cx_hash_no_throw(&zcashHashBlake2b.header, CX_LAST, b, b_len, out, out_len); } -uint16_t fp_uint64_to_str(char *out, uint16_t outLen, const uint64_t value, uint8_t decimals) { - return fpuint64_to_str(out, outLen, value, decimals); +uint16_t fp_uint64_to_str(char *out, uint16_t outLen, const uint64_t value, + uint8_t decimals) { + return fpuint64_to_str(out, outLen, value, decimals); } -void check_canary() { -} +void check_canary() {} -void _zemu_log_stack(uint8_t *buffer) { - zemu_log_stack((char *) buffer); -} +void _zemu_log_stack(uint8_t *buffer) { zemu_log_stack((char *)buffer); } +void c_aes256_encryptblock(const uint8_t *key, const uint8_t *in, + uint8_t *out) { + struct AES_ctx ctx; + AES_init_ctx(&ctx, key); -void c_aes256_encryptblock(const uint8_t *key, const uint8_t *in, uint8_t *out) { - struct AES_ctx ctx; - AES_init_ctx(&ctx, key); - - // encrypts in place, so we copy and encrypt - MEMCPY(out, in, AES_BLOCKLEN); - AES_ECB_encrypt(&ctx, out); + // encrypts in place, so we copy and encrypt + MEMCPY(out, in, AES_BLOCKLEN); + AES_ECB_encrypt(&ctx, out); } void c_jubjub_scalarmult(uint8_t *point, const uint8_t *scalar) { - jubjub_extendedpoint p; - jubjub_fq scal; - MEMCPY(scal, scalar, JUBJUB_FIELD_BYTES); - SWAP_ENDIAN_BYTES(scal); - - zxerr_t err = jubjub_extendedpoint_frombytes(&p, point); - if (err != zxerr_ok) { - MEMZERO(point, JUBJUB_FIELD_BYTES); - return; - } - jubjub_extendedpoint_scalarmult(&p, scal); - jubjub_extendedpoint_tobytes(point, p); + jubjub_extendedpoint p; + jubjub_fq scal; + MEMCPY(scal, scalar, JUBJUB_FIELD_BYTES); + SWAP_ENDIAN_BYTES(scal); + + zxerr_t err = jubjub_extendedpoint_frombytes(&p, point); + if (err != zxerr_ok) { + MEMZERO(point, JUBJUB_FIELD_BYTES); + return; + } + jubjub_extendedpoint_scalarmult(&p, scal); + jubjub_extendedpoint_tobytes(point, p); } void c_jubjub_spending_base_scalarmult(uint8_t *point, const uint8_t *scalar) { - jubjub_extendedpoint p; - jubjub_fq scal; - MEMCPY(scal, scalar, JUBJUB_FIELD_BYTES); - SWAP_ENDIAN_BYTES(scal); - MEMCPY(&p, &JUBJUB_GEN, sizeof(jubjub_extendedpoint)); - jubjub_extendedpoint_scalarmult(&p, scal); - jubjub_extendedpoint_tobytes(point, p); + jubjub_extendedpoint p; + jubjub_fq scal; + MEMCPY(scal, scalar, JUBJUB_FIELD_BYTES); + SWAP_ENDIAN_BYTES(scal); + MEMCPY(&p, &JUBJUB_GEN, sizeof(jubjub_extendedpoint)); + jubjub_extendedpoint_scalarmult(&p, scal); + jubjub_extendedpoint_tobytes(point, p); } // Replace functions affected by non-constant time opcodes // Overriding requires -z muldefs -// FIXME: add a python script to ensure that the correct version is used by inspecting app.asm +// FIXME: add a python script to ensure that the correct version is used by +// inspecting app.asm #if ENABLE_SDK_MULT -#define SWAP_BYTES(x, y, tmp) { \ - tmp = x; \ - x = y; \ - y = tmp;\ -} - -#define SWAP_ENDIAN(x, tmp) { \ - SWAP_BYTES(*x, *(x + 7), tmp); \ -SWAP_BYTES(*(x+1), *(x + 6), tmp); \ -SWAP_BYTES(*(x+2), *(x + 5), tmp); \ -SWAP_BYTES(*(x+3), *(x + 4), tmp); \ -} +#define SWAP_BYTES(x, y, tmp) \ + { \ + tmp = x; \ + x = y; \ + y = tmp; \ + } + +#define SWAP_ENDIAN(x, tmp) \ + { \ + SWAP_BYTES(*x, *(x + 7), tmp); \ + SWAP_BYTES(*(x + 1), *(x + 6), tmp); \ + SWAP_BYTES(*(x + 2), *(x + 5), tmp); \ + SWAP_BYTES(*(x + 3), *(x + 4), tmp); \ + } #define LMULSIZE sizeof(long long) -long long __attribute__ ((noinline)) __aeabi_lmul(long long a, long long b) { - uint8_t tmp = 0; - uint8_t *ptr = (uint8_t *)&a; +long long __attribute__((noinline)) __aeabi_lmul(long long a, long long b) { + uint8_t tmp = 0; + uint8_t *ptr = (uint8_t *)&a; - SWAP_ENDIAN(ptr, tmp); + SWAP_ENDIAN(ptr, tmp); - ptr = (uint8_t *)&b; - SWAP_ENDIAN(ptr, tmp); + ptr = (uint8_t *)&b; + SWAP_ENDIAN(ptr, tmp); - char result[2 * LMULSIZE]; - MEMZERO(result, 2 * LMULSIZE); - cx_math_mult((unsigned char *) &result, (unsigned char *) &a, (unsigned char *) &b, LMULSIZE); + char result[2 * LMULSIZE]; + MEMZERO(result, 2 * LMULSIZE); + cx_math_mult((unsigned char *)&result, (unsigned char *)&a, + (unsigned char *)&b, LMULSIZE); - SWAP_ENDIAN(ptr, tmp); - ptr = (uint8_t *)&a; - SWAP_ENDIAN(ptr, tmp); + SWAP_ENDIAN(ptr, tmp); + ptr = (uint8_t *)&a; + SWAP_ENDIAN(ptr, tmp); - ptr = (uint8_t *)&result[LMULSIZE]; - SWAP_ENDIAN(ptr, tmp); - return *((long long *) ptr); + ptr = (uint8_t *)&result[LMULSIZE]; + SWAP_ENDIAN(ptr, tmp); + return *((long long *)ptr); } #endif /* @@ -205,7 +215,8 @@ long long __multi3(long long a, long long b) { char result[2 * LMULSIZE]; MEMZERO(result, 2 * LMULSIZE); - cx_math_mult((unsigned char *) &result, (unsigned char *) &a_be, (unsigned char *) &b_be, LMULSIZE); + cx_math_mult((unsigned char *) &result, (unsigned char *) &a_be, (unsigned +char *) &b_be, LMULSIZE); long long r_le = 0; r_le |= result[LMULSIZE]; r_le <<= 8; @@ -220,13 +231,12 @@ long long __multi3(long long a, long long b) { } */ -//typedef struct { -// unsigned quot; -// unsigned rem; -//} __aeabi_uidivmod_result_t; +// typedef struct { +// unsigned quot; +// unsigned rem; +// } __aeabi_uidivmod_result_t; // //// FIXME: Complete implementation, redirect and enable -////__aeabi_uidivmod_result_t __aeabi_uidivmod(unsigned numerator, unsigned denominator) { -//// __aeabi_uidivmod_result_t r; -//// return r; +////__aeabi_uidivmod_result_t __aeabi_uidivmod(unsigned numerator, unsigned +///denominator) { / __aeabi_uidivmod_result_t r; / return r; ////} diff --git a/app/src/chacha.c b/app/src/chacha.c index 80e68666..598e3c8b 100644 --- a/app/src/chacha.c +++ b/app/src/chacha.c @@ -14,116 +14,118 @@ // Adapted from the public domain, estream code by D. Bernstein. // Adapted by Zondax -#include -#include -#include "os.h" -#include "cx.h" -#include "coin.h" -#include "app_main.h" #include "chacha.h" +#include "app_main.h" +#include "coin.h" +#include "cx.h" +#include "os.h" #include "zxmacros.h" +#include +#include - -#define U8TO32_LITTLE(p) \ - (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \ +#define U8TO32_LITTLE(p) \ + (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \ ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24)) // sigma contains the ChaCha constants, which happen to be an ASCII string. static const uint8_t sigma[16] = {'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'}; #define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n)))) // QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. -#define QUARTERROUND(a, b, c, d) \ - x[a] += x[b]; x[d] = ROTATE(x[d] ^ x[a], 16); \ - x[c] += x[d]; x[b] = ROTATE(x[b] ^ x[c], 12); \ - x[a] += x[b]; x[d] = ROTATE(x[d] ^ x[a], 8); \ - x[c] += x[d]; x[b] = ROTATE(x[b] ^ x[c], 7); +#define QUARTERROUND(a, b, c, d) \ + x[a] += x[b]; \ + x[d] = ROTATE(x[d] ^ x[a], 16); \ + x[c] += x[d]; \ + x[b] = ROTATE(x[b] ^ x[c], 12); \ + x[a] += x[b]; \ + x[d] = ROTATE(x[d] ^ x[a], 8); \ + x[c] += x[d]; \ + x[b] = ROTATE(x[b] ^ x[c], 7); void CRYPTO_hchacha20(uint8_t out[32], const uint8_t key[32], const uint8_t nonce[16]) { - uint32_t x[16]; - MEMCPY(x, sigma, sizeof(sigma)); - MEMCPY(&x[4], key, 32); - MEMCPY(&x[12], nonce, 16); - for (size_t i = 0; i < 20; i += 2) { - QUARTERROUND(0, 4, 8, 12) - QUARTERROUND(1, 5, 9, 13) - QUARTERROUND(2, 6, 10, 14) - QUARTERROUND(3, 7, 11, 15) - QUARTERROUND(0, 5, 10, 15) - QUARTERROUND(1, 6, 11, 12) - QUARTERROUND(2, 7, 8, 13) - QUARTERROUND(3, 4, 9, 14) - } - MEMCPY(out, &x[0], sizeof(uint32_t) * 4); - MEMCPY(&out[16], &x[12], sizeof(uint32_t) * 4); + uint32_t x[16]; + MEMCPY(x, sigma, sizeof(sigma)); + MEMCPY(&x[4], key, 32); + MEMCPY(&x[12], nonce, 16); + for (size_t i = 0; i < 20; i += 2) { + QUARTERROUND(0, 4, 8, 12) + QUARTERROUND(1, 5, 9, 13) + QUARTERROUND(2, 6, 10, 14) + QUARTERROUND(3, 7, 11, 15) + QUARTERROUND(0, 5, 10, 15) + QUARTERROUND(1, 6, 11, 12) + QUARTERROUND(2, 7, 8, 13) + QUARTERROUND(3, 4, 9, 14) + } + MEMCPY(out, &x[0], sizeof(uint32_t) * 4); + MEMCPY(&out[16], &x[12], sizeof(uint32_t) * 4); } -#define U32TO8_LITTLE(p, v) \ - { \ - (p)[0] = (v >> 0) & 0xff; \ - (p)[1] = (v >> 8) & 0xff; \ - (p)[2] = (v >> 16) & 0xff; \ - (p)[3] = (v >> 24) & 0xff; \ +#define U32TO8_LITTLE(p, v) \ + { \ + (p)[0] = (v >> 0) & 0xff; \ + (p)[1] = (v >> 8) & 0xff; \ + (p)[2] = (v >> 16) & 0xff; \ + (p)[3] = (v >> 24) & 0xff; \ } // chacha_core performs 20 rounds of ChaCha on the input words in // |input| and writes the 64 output bytes to |output|. void chacha_core(uint8_t *output, const uint32_t *input) { - uint32_t x[16]; - int i; - MEMCPY(x, input, sizeof(uint32_t) * 16); - for (i = 20; i > 0; i -= 2) { - QUARTERROUND(0, 4, 8, 12) - QUARTERROUND(1, 5, 9, 13) - QUARTERROUND(2, 6, 10, 14) - QUARTERROUND(3, 7, 11, 15) - QUARTERROUND(0, 5, 10, 15) - QUARTERROUND(1, 6, 11, 12) - QUARTERROUND(2, 7, 8, 13) - QUARTERROUND(3, 4, 9, 14) - } - for (i = 0; i < 16; ++i) { - x[i] += input[i]; - } - for (i = 0; i < 16; ++i) { - U32TO8_LITTLE(output + 4 * i, x[i]); - } + uint32_t x[16]; + int i; + MEMCPY(x, input, sizeof(uint32_t) * 16); + for (i = 20; i > 0; i -= 2) { + QUARTERROUND(0, 4, 8, 12) + QUARTERROUND(1, 5, 9, 13) + QUARTERROUND(2, 6, 10, 14) + QUARTERROUND(3, 7, 11, 15) + QUARTERROUND(0, 5, 10, 15) + QUARTERROUND(1, 6, 11, 12) + QUARTERROUND(2, 7, 8, 13) + QUARTERROUND(3, 4, 9, 14) + } + for (i = 0; i < 16; ++i) { + x[i] += input[i]; + } + for (i = 0; i < 16; ++i) { + U32TO8_LITTLE(output + 4 * i, x[i]); + } } -void chacha(uint8_t *out, const uint8_t *in, size_t in_len, - const uint8_t *key, const uint8_t *nonce, - uint32_t counter) { - uint32_t input[16]; - uint8_t buf[64]; - size_t todo, i; - input[0] = U8TO32_LITTLE(sigma + 0); - input[1] = U8TO32_LITTLE(sigma + 4); - input[2] = U8TO32_LITTLE(sigma + 8); - input[3] = U8TO32_LITTLE(sigma + 12); - input[4] = U8TO32_LITTLE(key + 0); - input[5] = U8TO32_LITTLE(key + 4); - input[6] = U8TO32_LITTLE(key + 8); - input[7] = U8TO32_LITTLE(key + 12); - input[8] = U8TO32_LITTLE(key + 16); - input[9] = U8TO32_LITTLE(key + 20); - input[10] = U8TO32_LITTLE(key + 24); - input[11] = U8TO32_LITTLE(key + 28); - input[12] = counter; - input[13] = U8TO32_LITTLE(nonce + 0); - input[14] = U8TO32_LITTLE(nonce + 4); - input[15] = U8TO32_LITTLE(nonce + 8); - while (in_len > 0) { - todo = sizeof(buf); - if (in_len < todo) { - todo = in_len; - } - chacha_core(buf, input); - for (i = 0; i < todo; i++) { - out[i] = in[i] ^ buf[i]; - } - out += todo; - in += todo; - in_len -= todo; - input[12]++; +void chacha(uint8_t *out, const uint8_t *in, size_t in_len, const uint8_t *key, + const uint8_t *nonce, uint32_t counter) { + uint32_t input[16]; + uint8_t buf[64]; + size_t todo, i; + input[0] = U8TO32_LITTLE(sigma + 0); + input[1] = U8TO32_LITTLE(sigma + 4); + input[2] = U8TO32_LITTLE(sigma + 8); + input[3] = U8TO32_LITTLE(sigma + 12); + input[4] = U8TO32_LITTLE(key + 0); + input[5] = U8TO32_LITTLE(key + 4); + input[6] = U8TO32_LITTLE(key + 8); + input[7] = U8TO32_LITTLE(key + 12); + input[8] = U8TO32_LITTLE(key + 16); + input[9] = U8TO32_LITTLE(key + 20); + input[10] = U8TO32_LITTLE(key + 24); + input[11] = U8TO32_LITTLE(key + 28); + input[12] = counter; + input[13] = U8TO32_LITTLE(nonce + 0); + input[14] = U8TO32_LITTLE(nonce + 4); + input[15] = U8TO32_LITTLE(nonce + 8); + while (in_len > 0) { + todo = sizeof(buf); + if (in_len < todo) { + todo = in_len; } + chacha_core(buf, input); + for (i = 0; i < todo; i++) { + out[i] = in[i] ^ buf[i]; + } + out += todo; + in += todo; + in_len -= todo; + input[12]++; + } } diff --git a/app/src/chacha.h b/app/src/chacha.h index 99473996..9ac95ba5 100644 --- a/app/src/chacha.h +++ b/app/src/chacha.h @@ -21,11 +21,9 @@ extern "C" { void CRYPTO_hchacha20(uint8_t out[32], const uint8_t key[32], const uint8_t nonce[16]); - -void chacha(uint8_t *out, const uint8_t *in, size_t in_len, - const uint8_t *key, const uint8_t *nonce, - uint32_t counter); +void chacha(uint8_t *out, const uint8_t *in, size_t in_len, const uint8_t *key, + const uint8_t *nonce, uint32_t counter); #if defined(__cplusplus) -} // extern C -#endif // OPENSSL_HEADER_CHACHA_INTERNAL +} // extern C +#endif // OPENSSL_HEADER_CHACHA_INTERNAL diff --git a/app/src/coin.h b/app/src/coin.h index 3de79f4f..0eee2f8d 100644 --- a/app/src/coin.h +++ b/app/src/coin.h @@ -1,107 +1,103 @@ /******************************************************************************* -* (c) 2019-2021 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019-2021 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #ifdef __cplusplus extern "C" { #endif -#define CLA 0x85 +#define CLA 0x85 -#define HDPATH_LEN_DEFAULT 5 +#define HDPATH_LEN_DEFAULT 5 -#define HDPATH_0_DEFAULT (0x80000000u | 0x2cu) -#define HDPATH_1_DEFAULT (0x80000000u | 0x85) -#define HDPATH_2_DEFAULT (0x80000000u | 0u) -#define HDPATH_3_DEFAULT (0u) -#define HDPATH_4_DEFAULT (0u) +#define HDPATH_0_DEFAULT (0x80000000u | 0x2cu) +#define HDPATH_1_DEFAULT (0x80000000u | 0x85) +#define HDPATH_2_DEFAULT (0x80000000u | 0u) +#define HDPATH_3_DEFAULT (0u) +#define HDPATH_4_DEFAULT (0u) -#define HDPATH_0_TESTNET (0x80000000u | 0x2cu) -#define HDPATH_1_TESTNET (0x80000000u | 0x1u) +#define HDPATH_0_TESTNET (0x80000000u | 0x2cu) +#define HDPATH_1_TESTNET (0x80000000u | 0x1u) // compressed key -#define PK_LEN_SECP256K1 33u +#define PK_LEN_SECP256K1 33u // sapling address [11+32] -#define ADDR_LEN_SAPLING 43u +#define ADDR_LEN_SAPLING 43u // ivk -#define LEN_IVK 32u - -//ak, nsk -#define LEN_PGK 64u - -#define ENABLE_SDK_MULT 0 - -#define DATA_LENGTH_GET_IVK 4 //ZIP32-path -#define DATA_LENGTH_GET_OVK 4 //ZIP32-path -#define DATA_LENGTH_GET_FVK 4 //ZIP32-path -#define DATA_LENGTH_GET_NF 44 // ZIP32-path + 8-byte note position + 32-byte note commitment -#define DATA_LENGTH_GET_ADDR_SAPLING 4 //ZIP32-path -#define DATA_LENGTH_GET_DIV_LIST 15 //ZIP32-path + 11-byte index -#define DATA_LENGTH_GET_ADDR_DIV 15 //ZIP32-path + 11-byte div - -#define INS_GET_VERSION 0x00 -#define INS_GET_ADDR_SECP256K1 0x01 -#define INS_SIGN_SECP256K1 0x02 -#define INS_GET_DIV_LIST 0x09 -#define INS_GET_ADDR_SAPLING_DIV 0x10 -#define INS_GET_ADDR_SAPLING 0x11 -#define INS_SIGN_SAPLING 0x12 - -#define INS_INIT_TX 0xa0 -#define INS_KEY_EXCHANGE 0xaa -#define INS_EXTRACT_SPEND 0xa1 -#define INS_EXTRACT_OUTPUT 0xa2 -#define INS_CHECKANDSIGN 0xa3 -#define INS_EXTRACT_SPENDSIG 0xa4 -#define INS_EXTRACT_TRANSSIG 0xa5 - -#define INS_GET_IVK 0xf0 -#define INS_GET_OVK 0xf1 -#define INS_GET_NF 0xf2 -#define INS_GET_FVK 0xf3 -#define INS_CRASH_TEST 0xff +#define LEN_IVK 32u + +// ak, nsk +#define LEN_PGK 64u + +#define ENABLE_SDK_MULT 0 + +#define DATA_LENGTH_GET_IVK 4 // ZIP32-path +#define DATA_LENGTH_GET_OVK 4 // ZIP32-path +#define DATA_LENGTH_GET_FVK 4 // ZIP32-path +#define DATA_LENGTH_GET_NF \ + 44 // ZIP32-path + 8-byte note position + 32-byte note commitment +#define DATA_LENGTH_GET_ADDR_SAPLING 4 // ZIP32-path +#define DATA_LENGTH_GET_DIV_LIST 15 // ZIP32-path + 11-byte index +#define DATA_LENGTH_GET_ADDR_DIV 15 // ZIP32-path + 11-byte div + +#define INS_GET_VERSION 0x00 +#define INS_GET_ADDR_SECP256K1 0x01 +#define INS_SIGN_SECP256K1 0x02 +#define INS_GET_DIV_LIST 0x09 +#define INS_GET_ADDR_SAPLING_DIV 0x10 +#define INS_GET_ADDR_SAPLING 0x11 +#define INS_SIGN_SAPLING 0x12 + +#define INS_INIT_TX 0xa0 +#define INS_KEY_EXCHANGE 0xaa +#define INS_EXTRACT_SPEND 0xa1 +#define INS_EXTRACT_OUTPUT 0xa2 +#define INS_CHECKANDSIGN 0xa3 +#define INS_EXTRACT_SPENDSIG 0xa4 +#define INS_EXTRACT_TRANSSIG 0xa5 + +#define INS_GET_IVK 0xf0 +#define INS_GET_OVK 0xf1 +#define INS_GET_NF 0xf2 +#define INS_GET_FVK 0xf3 +#define INS_CRASH_TEST 0xff typedef enum { - addr_secp256k1 = 0, - addr_sapling = 1, - addr_sapling_div = 2, + addr_secp256k1 = 0, + addr_sapling = 1, + addr_sapling_div = 2, } address_kind_e; -typedef enum { - key_ivk = 0, - key_ovk = 1, - key_fvk = 2, - nf = 3 -} key_type_e; +typedef enum { key_ivk = 0, key_ovk = 1, key_fvk = 2, nf = 3 } key_type_e; -#define VIEW_ADDRESS_OFFSET_SECP256K1 PK_LEN_SECP256K1 -#define VIEW_ADDRESS_OFFSET_SAPLING ADDR_LEN_SAPLING +#define VIEW_ADDRESS_OFFSET_SECP256K1 PK_LEN_SECP256K1 +#define VIEW_ADDRESS_OFFSET_SAPLING ADDR_LEN_SAPLING -#define MENU_MAIN_APP_LINE1 "Zcash" -#define MENU_MAIN_APP_LINE2 "Ready" -#define APPVERSION_LINE1 "Zcash" -#define APPVERSION_LINE2 ("v" APPVERSION) +#define MENU_MAIN_APP_LINE1 "Zcash" +#define MENU_MAIN_APP_LINE2 "Ready" +#define APPVERSION_LINE1 "Zcash" +#define APPVERSION_LINE2 ("v" APPVERSION) -#define MENU_MAIN_APP_LINE2_SECRET "?" -#define COIN_SECRET_REQUIRED_CLICKS 0 +#define MENU_MAIN_APP_LINE2_SECRET "?" +#define COIN_SECRET_REQUIRED_CLICKS 0 -#define COIN_AMOUNT_DECIMAL_PLACES 18 // FIXME: Check this -#define CRYPTO_BLOB_SKIP_BYTES 0 +#define COIN_AMOUNT_DECIMAL_PLACES 18 // FIXME: Check this +#define CRYPTO_BLOB_SKIP_BYTES 0 #ifdef __cplusplus } diff --git a/app/src/common/actions.c b/app/src/common/actions.c index b76094bd..ce4d0916 100644 --- a/app/src/common/actions.c +++ b/app/src/common/actions.c @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2021 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2021 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include "actions.h" #include "tx.h" diff --git a/app/src/common/actions.h b/app/src/common/actions.h index 3d3679d7..13e11d11 100644 --- a/app/src/common/actions.h +++ b/app/src/common/actions.h @@ -1,70 +1,70 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once -#include -#include "crypto.h" -#include "tx.h" #include "apdu_codes.h" -#include "zcash_apdu_errors.h" -#include -#include "coin.h" #include "app_main.h" +#include "coin.h" +#include "crypto.h" #include "nvdata.h" #include "parser.h" +#include "tx.h" +#include "zcash_apdu_errors.h" +#include +#include typedef struct { - address_kind_e kind; - uint8_t len; + address_kind_e kind; + uint8_t len; } address_state_t; typedef struct { - key_type_e kind; - uint8_t len; + key_type_e kind; + uint8_t len; } key_state_t; extern address_state_t action_addrResponse; extern key_state_t key_state; __Z_INLINE void app_reject() { - transaction_reset(); - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - view_tx_state(); - set_code(G_io_apdu_buffer, 0, APDU_CODE_COMMAND_NOT_ALLOWED); - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); + transaction_reset(); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + view_tx_state(); + set_code(G_io_apdu_buffer, 0, APDU_CODE_COMMAND_NOT_ALLOWED); + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); } __Z_INLINE void app_reply_key() { - set_code(G_io_apdu_buffer, key_state.len, APDU_CODE_OK); - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, key_state.len + 2); + set_code(G_io_apdu_buffer, key_state.len, APDU_CODE_OK); + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, key_state.len + 2); } __Z_INLINE void app_reply_address() { - set_code(G_io_apdu_buffer, action_addrResponse.len, APDU_CODE_OK); - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, action_addrResponse.len + 2); + set_code(G_io_apdu_buffer, action_addrResponse.len, APDU_CODE_OK); + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, action_addrResponse.len + 2); } __Z_INLINE void app_reply_error() { - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - set_code(G_io_apdu_buffer, 0, APDU_CODE_DATA_INVALID); - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + set_code(G_io_apdu_buffer, 0, APDU_CODE_DATA_INVALID); + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); } __Z_INLINE void app_reply_hash() { - view_tx_state(); - set_code(G_io_apdu_buffer, 32, APDU_CODE_OK); - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 32 + 2); + view_tx_state(); + set_code(G_io_apdu_buffer, 32, APDU_CODE_OK); + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 32 + 2); } diff --git a/app/src/common/main.c b/app/src/common/main.c index c4de1750..d7eb28e6 100644 --- a/app/src/common/main.c +++ b/app/src/common/main.c @@ -1,43 +1,38 @@ /******************************************************************************* -* (c) 2016 Ledger -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2016 Ledger + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include "app_main.h" #include "view.h" #include -__attribute__((section(".boot"))) int -main(void) { - // exit critical section - __asm volatile("cpsie i"); +__attribute__((section(".boot"))) int main(void) { + // exit critical section + __asm volatile("cpsie i"); - view_init(); - os_boot(); + view_init(); + os_boot(); - BEGIN_TRY - { - TRY - { - app_init(); - app_main(); - } - CATCH_OTHER(e) - {} - FINALLY - {} + BEGIN_TRY { + TRY { + app_init(); + app_main(); } - END_TRY; + CATCH_OTHER(e) {} + FINALLY {} + } + END_TRY; } diff --git a/app/src/common/tx.c b/app/src/common/tx.c index 07ec2fdb..cf1123f6 100644 --- a/app/src/common/tx.c +++ b/app/src/common/tx.c @@ -1,36 +1,37 @@ /******************************************************************************* -* (c) 2019 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include "tx.h" #include "apdu_codes.h" #include "buffering.h" #include "parser.h" -#include #include "zxmacros.h" +#include // Ram uint8_t ram_buffer[RAM_BUFFER_SIZE]; // Flash typedef struct { - uint8_t buffer[FLASH_BUFFER_SIZE]; + uint8_t buffer[FLASH_BUFFER_SIZE]; } storage_t; -#if defined(TARGET_NANOS) || defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX) -storage_t NV_CONST N_appdata_impl __attribute__ ((aligned(64))); +#if defined(TARGET_NANOS) || defined(TARGET_NANOX) || \ + defined(TARGET_NANOS2) || defined(TARGET_STAX) +storage_t NV_CONST N_appdata_impl __attribute__((aligned(64))); #define N_appdata (*(NV_VOLATILE storage_t *)PIC(&N_appdata_impl)) #endif @@ -38,87 +39,71 @@ static parser_tx_t tx_obj; static parser_context_t ctx_parsed_tx; void tx_initialize() { - buffering_init( - ram_buffer, - sizeof(ram_buffer), - (uint8_t *) N_appdata.buffer, - sizeof(N_appdata.buffer) - ); + buffering_init(ram_buffer, sizeof(ram_buffer), (uint8_t *)N_appdata.buffer, + sizeof(N_appdata.buffer)); } -void tx_reset() { - buffering_reset(); -} +void tx_reset() { buffering_reset(); } uint32_t tx_append(unsigned char *buffer, uint32_t length) { - return buffering_append(buffer, length); + return buffering_append(buffer, length); } -uint32_t tx_get_buffer_length() { - return buffering_get_buffer()->pos; -} +uint32_t tx_get_buffer_length() { return buffering_get_buffer()->pos; } -uint8_t *tx_get_buffer() { - return buffering_get_buffer()->data; -} +uint8_t *tx_get_buffer() { return buffering_get_buffer()->data; } const char *tx_parse() { - MEMZERO(&tx_obj, sizeof(tx_obj)); + MEMZERO(&tx_obj, sizeof(tx_obj)); - uint8_t err = parser_parse( - &ctx_parsed_tx, - tx_get_buffer(), - tx_get_buffer_length()); + uint8_t err = + parser_parse(&ctx_parsed_tx, tx_get_buffer(), tx_get_buffer_length()); - if (err != parser_ok) { - return parser_getErrorDescription(err); - } + if (err != parser_ok) { + return parser_getErrorDescription(err); + } - err = parser_validate(); - CHECK_APP_CANARY() + err = parser_validate(); + CHECK_APP_CANARY() - if (err != parser_ok) { - return parser_getErrorDescription(err); - } + if (err != parser_ok) { + return parser_getErrorDescription(err); + } - return NULL; + return NULL; } zxerr_t tx_getNumItems(uint8_t *num_items) { - parser_error_t err = parser_getNumItems(num_items); + parser_error_t err = parser_getNumItems(num_items); - if (err != parser_ok) { - return zxerr_no_data; - } + if (err != parser_ok) { + return zxerr_no_data; + } - return zxerr_ok; + return zxerr_ok; } -zxerr_t tx_getItem(int8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outVal, uint16_t outValLen, - uint8_t pageIdx, uint8_t *pageCount) { - uint8_t numItems = 0; +zxerr_t tx_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, + char *outVal, uint16_t outValLen, uint8_t pageIdx, + uint8_t *pageCount) { + uint8_t numItems = 0; - CHECK_ZXERR(tx_getNumItems(&numItems)) + CHECK_ZXERR(tx_getNumItems(&numItems)) - if (displayIdx < 0 || displayIdx > numItems) { - return zxerr_no_data; - } + if (displayIdx < 0 || displayIdx > numItems) { + return zxerr_no_data; + } - parser_error_t err = parser_getItem(displayIdx, - outKey, outKeyLen, - outVal, outValLen, - pageIdx, pageCount); + parser_error_t err = parser_getItem(displayIdx, outKey, outKeyLen, outVal, + outValLen, pageIdx, pageCount); - // Convert error codes - if (err == parser_no_data || - err == parser_display_idx_out_of_range || - err == parser_display_page_out_of_range) - return zxerr_no_data; + // Convert error codes + if (err == parser_no_data || err == parser_display_idx_out_of_range || + err == parser_display_page_out_of_range) + return zxerr_no_data; - if (err != parser_ok) - return zxerr_unknown; + if (err != parser_ok) + return zxerr_unknown; - return zxerr_ok; + return zxerr_ok; } diff --git a/app/src/common/tx.h b/app/src/common/tx.h index e11f5098..7a501fcb 100644 --- a/app/src/common/tx.h +++ b/app/src/common/tx.h @@ -1,22 +1,22 @@ /******************************************************************************* -* (c) 2019 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once -#include "os.h" #include "coin.h" +#include "os.h" #include "zxerror.h" #if defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX) @@ -56,7 +56,6 @@ const char *tx_parse(); zxerr_t tx_getNumItems(uint8_t *num_items); /// Gets an specific item from the transaction (including paging) -zxerr_t tx_getItem(int8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outValue, uint16_t outValueLen, - uint8_t pageIdx, uint8_t *pageCount); +zxerr_t tx_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, + char *outValue, uint16_t outValueLen, uint8_t pageIdx, + uint8_t *pageCount); diff --git a/app/src/constants.h b/app/src/constants.h index 0ee15dfb..9d95186c 100644 --- a/app/src/constants.h +++ b/app/src/constants.h @@ -1,108 +1,107 @@ /******************************************************************************* -* (c) 2018 - 2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 - 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once // CRYPTO File -#define CHECKSUM_LENGTH 4 - -#define SK_SECP256K1_SIZE 32 -#define PUB_KEY_SIZE 32 -#define DER_MAX_SIZE 73 -#define AK_SIZE 32 -#define NSK_SIZE 32 -#define ASK_SIZE 32 -#define DK_SIZE 32 -#define NK_SIZE 32 -#define ED25519_SK_SIZE 64 -#define IVK_SIZE 32 -#define ZIP32_SEED_SIZE 64 -#define ZIP32_PATH_SIZE 4 -#define RND_SIZE 32 -#define NULLIFIER_SIZE 32 -#define RK_SIZE 32 - -#define ESK_SIZE 32 -#define EPK_SIZE 32 -#define NOTE_POSITION_SIZE 8 -#define NOTE_COMMITMENT_SIZE 32 -#define VALUE_COMMITMENT_SIZE 32 -#define ANCHOR_SIZE 32 -#define HASH_SIZE 32 -#define SESSION_KEY_SIZE 32 -#define GD_SIZE 32 -#define SHARED_KEY_SIZE 32 -#define OUT_KEY_SIZE 32 -#define ENC_CIPHER_SIZE 64 -#define ENC_CIPHER_HALVE_SIZE 32 - -#define OUTPUT_ENC_MEMO_SIZE 564-52 -#define OUTPUT_ENC_AEAD_TAG_SIZE 580-564 -#define OUTPUT_OUT_SIZE 80 // OutputDescription, field out_ciphertext: [u8; 80], - -#define COMPACT_OUT_SIZE 53 -#define PRF_INPUT_SIZE 128 -#define MAX_SIZE 161 -#define SIG_R_SIZE 32 -#define SIG_S_SIZE 32 -#define SCRIPT_CONSTS_SIZE 4 -#define PEDERSEN_INPUT_SIZE 73 -#define CHACHA_NONCE_SIZE 12 - -#define MASK_HARDENED 0x80000000 - -#define VERSION_SIZE 2 -#define CHECKSUM_SIZE 4 -#define VERSION_P2SH 0x1CBD -#define VERSION_P2PKH 0x1CB8 -#define BECH32_HRP "zs" -#define BECH32_HRP_TEST "ztestsapling" - +#define CHECKSUM_LENGTH 4 + +#define SK_SECP256K1_SIZE 32 +#define PUB_KEY_SIZE 32 +#define DER_MAX_SIZE 73 +#define AK_SIZE 32 +#define NSK_SIZE 32 +#define ASK_SIZE 32 +#define DK_SIZE 32 +#define NK_SIZE 32 +#define ED25519_SK_SIZE 64 +#define IVK_SIZE 32 +#define ZIP32_SEED_SIZE 64 +#define ZIP32_PATH_SIZE 4 +#define RND_SIZE 32 +#define NULLIFIER_SIZE 32 +#define RK_SIZE 32 + +#define ESK_SIZE 32 +#define EPK_SIZE 32 +#define NOTE_POSITION_SIZE 8 +#define NOTE_COMMITMENT_SIZE 32 +#define VALUE_COMMITMENT_SIZE 32 +#define ANCHOR_SIZE 32 +#define HASH_SIZE 32 +#define SESSION_KEY_SIZE 32 +#define GD_SIZE 32 +#define SHARED_KEY_SIZE 32 +#define OUT_KEY_SIZE 32 +#define ENC_CIPHER_SIZE 64 +#define ENC_CIPHER_HALVE_SIZE 32 + +#define OUTPUT_ENC_MEMO_SIZE 564 - 52 +#define OUTPUT_ENC_AEAD_TAG_SIZE 580 - 564 +#define OUTPUT_OUT_SIZE 80 // OutputDescription, field out_ciphertext: [u8; 80], + +#define COMPACT_OUT_SIZE 53 +#define PRF_INPUT_SIZE 128 +#define MAX_SIZE 161 +#define SIG_R_SIZE 32 +#define SIG_S_SIZE 32 +#define SCRIPT_CONSTS_SIZE 4 +#define PEDERSEN_INPUT_SIZE 73 +#define CHACHA_NONCE_SIZE 12 + +#define MASK_HARDENED 0x80000000 + +#define VERSION_SIZE 2 +#define CHECKSUM_SIZE 4 +#define VERSION_P2SH 0x1CBD +#define VERSION_P2PKH 0x1CB8 +#define BECH32_HRP "zs" +#define BECH32_HRP_TEST "ztestsapling" // NVDATA File -//fixme: maybe increase some of these -#define T_IN_LIST_SIZE 5 -#define T_OUT_LIST_SIZE 5 -#define SPEND_LIST_SIZE 5 -#define OUTPUT_LIST_SIZE 5 - -#define PREVOUT_SIZE 36 -#define SEQUENCE_SIZE 4 -#define T_OUTPUT_SIZE 34 // script size (26) + value size (uint64_t -> 8) - -#define PKD_SIZE 32 -#define RCM_SIZE 32 -#define ALPHA_SIZE 32 -#define DIV_SIZE 11 -#define DIV_INDEX_SIZE 11 -#define DIV_LIST_LENGTH 20 -#define DIV_DEFAULT_LIST_LEN 4 -#define MAX_SIZE_BUF_ADDR 143 - -#define SESSION_KEY_SIZE 32 - -#define OVK_SIZE 32 -#define OVK_SET_SIZE 1 + OVK_SIZE -#define RSEED_SIZE 32 -#define RCM_V_SIZE 32 - -#define SCRIPT_SIZE 26 -#define PATH_SIZE 5 - -#define SIGNATURE_SIZE SIG_R_SIZE + SIG_S_SIZE - -#define TX_VERSION_SAPLING 4 -#define TX_VERSION_NU5 5 +// fixme: maybe increase some of these +#define T_IN_LIST_SIZE 5 +#define T_OUT_LIST_SIZE 5 +#define SPEND_LIST_SIZE 5 +#define OUTPUT_LIST_SIZE 5 + +#define PREVOUT_SIZE 36 +#define SEQUENCE_SIZE 4 +#define T_OUTPUT_SIZE 34 // script size (26) + value size (uint64_t -> 8) + +#define PKD_SIZE 32 +#define RCM_SIZE 32 +#define ALPHA_SIZE 32 +#define DIV_SIZE 11 +#define DIV_INDEX_SIZE 11 +#define DIV_LIST_LENGTH 20 +#define DIV_DEFAULT_LIST_LEN 4 +#define MAX_SIZE_BUF_ADDR 143 + +#define SESSION_KEY_SIZE 32 + +#define OVK_SIZE 32 +#define OVK_SET_SIZE 1 + OVK_SIZE +#define RSEED_SIZE 32 +#define RCM_V_SIZE 32 + +#define SCRIPT_SIZE 26 +#define PATH_SIZE 5 + +#define SIGNATURE_SIZE SIG_R_SIZE + SIG_S_SIZE + +#define TX_VERSION_SAPLING 4 +#define TX_VERSION_NU5 5 diff --git a/app/src/crypto.c b/app/src/crypto.c index cce9ae57..543d55d3 100644 --- a/app/src/crypto.c +++ b/app/src/crypto.c @@ -1,1487 +1,1616 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include "crypto.h" -#include "constants.h" -#include "coin.h" -#include "zxformat.h" -#include "zxmacros.h" #include "base58.h" -#include "rslib.h" #include "bech32.h" +#include "chacha.h" +#include "coin.h" +#include "constants.h" +#include "index_NU5.h" +#include "index_sapling.h" +#include "lcx_ripemd160.h" #include "nvdata.h" +#include "parser_common.h" +#include "parser_impl.h" +#include "rslib.h" #include "sighash.h" #include "txid.h" -#include "index_sapling.h" -#include "index_NU5.h" -#include "parser_impl.h" -#include "parser_common.h" -#include "chacha.h" -#include "lcx_ripemd160.h" +#include "zxformat.h" +#include "zxmacros.h" uint32_t hdPath[HDPATH_LEN_DEFAULT]; -#define CHECK_ZXERROR_AND_CLEAN(CALL) \ - do { \ - zxerr_t __zxerror = CALL; \ - if (__zxerror != zxerr_ok) { \ - MEMZERO(&tmp, sizeof(tmp)); \ - MEMZERO(buffer, bufferLen); \ - return __zxerror; \ - } \ +#define CHECK_ZXERROR_AND_CLEAN(CALL) \ + do { \ + zxerr_t __zxerror = CALL; \ + if (__zxerror != zxerr_ok) { \ + MEMZERO(&tmp, sizeof(tmp)); \ + MEMZERO(buffer, bufferLen); \ + return __zxerror; \ + } \ } while (0); typedef enum { - EXTRACT_SAPLING_E0 = 0xE0, - EXTRACT_SAPLING_E1 = 0xE1, - EXTRACT_SAPLING_E2 = 0xE2, - EXTRACT_SAPLING_E3 = 0xE3, - EXTRACT_SAPLING_E4 = 0xE4, - EXTRACT_SAPLING_E5 = 0xE5, - EXTRACT_SAPLING_E6 = 0xE6, - EXTRACT_SAPLING_E7 = 0xE7, - EXTRACT_SAPLING_E8 = 0xE8, - EXTRACT_SAPLING_E9 = 0xE9, - EXTRACT_SAPLING_EA = 0xEA, - EXTRACT_SAPLING_EB = 0xEB, - EXTRACT_SAPLING_EC = 0xEC, - EXTRACT_SAPLING_ED = 0xED, + EXTRACT_SAPLING_E0 = 0xE0, + EXTRACT_SAPLING_E1 = 0xE1, + EXTRACT_SAPLING_E2 = 0xE2, + EXTRACT_SAPLING_E3 = 0xE3, + EXTRACT_SAPLING_E4 = 0xE4, + EXTRACT_SAPLING_E5 = 0xE5, + EXTRACT_SAPLING_E6 = 0xE6, + EXTRACT_SAPLING_E7 = 0xE7, + EXTRACT_SAPLING_E8 = 0xE8, + EXTRACT_SAPLING_E9 = 0xE9, + EXTRACT_SAPLING_EA = 0xEA, + EXTRACT_SAPLING_EB = 0xEB, + EXTRACT_SAPLING_EC = 0xEC, + EXTRACT_SAPLING_ED = 0xED, } extract_sapling_e; #include "cx.h" typedef struct { - uint8_t publicKey[PK_LEN_SECP256K1]; - uint8_t address[50]; + uint8_t publicKey[PK_LEN_SECP256K1]; + uint8_t address[50]; } __attribute__((packed)) answer_t; void ripemd160(uint8_t *in, uint16_t inLen, uint8_t *out) { - cx_ripemd160_t rip160; - cx_ripemd160_init(&rip160); - cx_hash_no_throw(&rip160.header, CX_LAST, in, inLen, out, CX_RIPEMD160_SIZE); + cx_ripemd160_t rip160; + cx_ripemd160_init(&rip160); + cx_hash_no_throw(&rip160.header, CX_LAST, in, inLen, out, CX_RIPEMD160_SIZE); } // According to 5.6 Encodings of Addresses and Keys typedef struct { - // [ADDRESS ] - // [EXTENDED RIPEMD-160][Checksum 4-bytes] - // [EXTENDED RIPEMD-160][Checksum-------------------------] - // [version][RIPEMD-160] - union { - uint8_t address[VERSION_SIZE + CX_RIPEMD160_SIZE + CHECKSUM_SIZE]; - - struct { - uint8_t extended_ripe[VERSION_SIZE + CX_RIPEMD160_SIZE]; - uint8_t sha256_checksum[CX_SHA256_SIZE]; - }; - - union { - // [EXTENDED RIPEMD-160] - // [version][RIPEMD-160] - struct { - uint8_t version[VERSION_SIZE]; - uint8_t ripe_sha256_pk[CX_RIPEMD160_SIZE]; - }; - }; + // [ADDRESS ] + // [EXTENDED RIPEMD-160][Checksum 4-bytes] + // [EXTENDED RIPEMD-160][Checksum-------------------------] + // [version][RIPEMD-160] + union { + uint8_t address[VERSION_SIZE + CX_RIPEMD160_SIZE + CHECKSUM_SIZE]; + + struct { + uint8_t extended_ripe[VERSION_SIZE + CX_RIPEMD160_SIZE]; + uint8_t sha256_checksum[CX_SHA256_SIZE]; }; - // Temporary buffers union { - uint8_t sha256_pk[CX_SHA256_SIZE]; - uint8_t sha256_extended_ripe[CX_SHA256_SIZE]; + // [EXTENDED RIPEMD-160] + // [version][RIPEMD-160] + struct { + uint8_t version[VERSION_SIZE]; + uint8_t ripe_sha256_pk[CX_RIPEMD160_SIZE]; + }; }; -} __attribute__((packed)) address_temp_t; + }; + // Temporary buffers + union { + uint8_t sha256_pk[CX_SHA256_SIZE]; + uint8_t sha256_extended_ripe[CX_SHA256_SIZE]; + }; +} __attribute__((packed)) address_temp_t; static zxerr_t crypto_extractPublicKey(uint8_t *pubKey, uint16_t pubKeyLen) { - if (pubKey == NULL || pubKeyLen < PK_LEN_SECP256K1) { - return zxerr_invalid_crypto_settings; - } - - cx_ecfp_public_key_t cx_publicKey = {0}; - cx_ecfp_private_key_t cx_privateKey = {0}; - uint8_t privateKeyData[64] = {0}; - - zxerr_t error = zxerr_unknown; - CATCH_CXERROR(os_derive_bip32_no_throw(CX_CURVE_256K1, - hdPath, - HDPATH_LEN_DEFAULT, - privateKeyData, NULL)) - - CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_256K1, privateKeyData, SK_SECP256K1_SIZE, &cx_privateKey)) - CATCH_CXERROR(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, NULL, 0, &cx_publicKey)) - CATCH_CXERROR(cx_ecfp_generate_pair_no_throw(CX_CURVE_256K1, &cx_publicKey, &cx_privateKey, 1)) - - // Format pubkey - for (int i = 0; i < PUB_KEY_SIZE; i++) { - pubKey[i] = cx_publicKey.W[64 - i]; - } - cx_publicKey.W[0] = cx_publicKey.W[64] & 1 ? 0x03 : 0x02; // "Compress" public key in place - if ((cx_publicKey.W[PUB_KEY_SIZE] & 1) != 0) { - pubKey[PUB_KEY_SIZE - 1] |= 0x80; - } - memcpy(pubKey, cx_publicKey.W, PK_LEN_SECP256K1); - error = zxerr_ok; + if (pubKey == NULL || pubKeyLen < PK_LEN_SECP256K1) { + return zxerr_invalid_crypto_settings; + } + + cx_ecfp_public_key_t cx_publicKey = {0}; + cx_ecfp_private_key_t cx_privateKey = {0}; + uint8_t privateKeyData[64] = {0}; + + zxerr_t error = zxerr_unknown; + CATCH_CXERROR(os_derive_bip32_no_throw( + CX_CURVE_256K1, hdPath, HDPATH_LEN_DEFAULT, privateKeyData, NULL)) + + CATCH_CXERROR(cx_ecfp_init_private_key_no_throw( + CX_CURVE_256K1, privateKeyData, SK_SECP256K1_SIZE, &cx_privateKey)) + CATCH_CXERROR( + cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, NULL, 0, &cx_publicKey)) + CATCH_CXERROR(cx_ecfp_generate_pair_no_throw(CX_CURVE_256K1, &cx_publicKey, + &cx_privateKey, 1)) + + // Format pubkey + for (int i = 0; i < PUB_KEY_SIZE; i++) { + pubKey[i] = cx_publicKey.W[64 - i]; + } + cx_publicKey.W[0] = + cx_publicKey.W[64] & 1 ? 0x03 : 0x02; // "Compress" public key in place + if ((cx_publicKey.W[PUB_KEY_SIZE] & 1) != 0) { + pubKey[PUB_KEY_SIZE - 1] |= 0x80; + } + memcpy(pubKey, cx_publicKey.W, PK_LEN_SECP256K1); + error = zxerr_ok; catch_cx_error: - MEMZERO(&cx_privateKey, sizeof(cx_privateKey)); - MEMZERO(privateKeyData, sizeof(privateKeyData)); + MEMZERO(&cx_privateKey, sizeof(cx_privateKey)); + MEMZERO(privateKeyData, sizeof(privateKeyData)); - if (error != zxerr_ok) { - MEMZERO(pubKey, pubKeyLen); - } + if (error != zxerr_ok) { + MEMZERO(pubKey, pubKeyLen); + } - return error; + return error; } // handleGetAddrSecp256K1 -zxerr_t crypto_fillAddress_secp256k1(uint8_t *buffer, uint16_t buffer_len, uint16_t *replyLen) { - if (buffer_len < sizeof(answer_t)) { - return zxerr_unknown; - } - - zemu_log_stack("crypto_fillAddress_secp256k1"); - - *replyLen = 0; - MEMZERO(buffer, buffer_len); - answer_t *const answer = (answer_t *) buffer; - - CHECK_ZXERR(crypto_extractPublicKey(answer->publicKey, sizeof_field(answer_t, publicKey))); - - address_temp_t address_temp; - - // extended-ripemd-160 = [version][ripemd-160(sha256(pk))] - address_temp.version[0] = VERSION_P2PKH >> 8; - address_temp.version[1] = VERSION_P2PKH & 0xFF; - cx_hash_sha256(answer->publicKey, PK_LEN_SECP256K1, address_temp.sha256_pk, CX_SHA256_SIZE); // SHA256 - ripemd160(address_temp.sha256_pk, CX_SHA256_SIZE, address_temp.ripe_sha256_pk); // RIPEMD-160 - - // checksum = sha256(sha256(extended-ripe)) - cx_hash_sha256(address_temp.extended_ripe, CX_RIPEMD160_SIZE + VERSION_SIZE, address_temp.sha256_extended_ripe, CX_SHA256_SIZE); - cx_hash_sha256(address_temp.sha256_extended_ripe, CX_SHA256_SIZE, address_temp.sha256_checksum, CX_SHA256_SIZE); - - // 7. 25 bytes BTC address = [extended ripemd-160][checksum] - // Encode as base58 - size_t outLen = sizeof_field(answer_t, address); - int err = encode_base58(address_temp.address, VERSION_SIZE + CX_RIPEMD160_SIZE + CHECKSUM_SIZE, answer->address, &outLen); - if(err != 0){ - return zxerr_unknown; - } - *replyLen = PK_LEN_SECP256K1 + outLen; - return zxerr_ok; +zxerr_t crypto_fillAddress_secp256k1(uint8_t *buffer, uint16_t buffer_len, + uint16_t *replyLen) { + if (buffer_len < sizeof(answer_t)) { + return zxerr_unknown; + } + + zemu_log_stack("crypto_fillAddress_secp256k1"); + + *replyLen = 0; + MEMZERO(buffer, buffer_len); + answer_t *const answer = (answer_t *)buffer; + + CHECK_ZXERR(crypto_extractPublicKey(answer->publicKey, + sizeof_field(answer_t, publicKey))); + + address_temp_t address_temp; + + // extended-ripemd-160 = [version][ripemd-160(sha256(pk))] + address_temp.version[0] = VERSION_P2PKH >> 8; + address_temp.version[1] = VERSION_P2PKH & 0xFF; + cx_hash_sha256(answer->publicKey, PK_LEN_SECP256K1, address_temp.sha256_pk, + CX_SHA256_SIZE); // SHA256 + ripemd160(address_temp.sha256_pk, CX_SHA256_SIZE, + address_temp.ripe_sha256_pk); // RIPEMD-160 + + // checksum = sha256(sha256(extended-ripe)) + cx_hash_sha256(address_temp.extended_ripe, CX_RIPEMD160_SIZE + VERSION_SIZE, + address_temp.sha256_extended_ripe, CX_SHA256_SIZE); + cx_hash_sha256(address_temp.sha256_extended_ripe, CX_SHA256_SIZE, + address_temp.sha256_checksum, CX_SHA256_SIZE); + + // 7. 25 bytes BTC address = [extended ripemd-160][checksum] + // Encode as base58 + size_t outLen = sizeof_field(answer_t, address); + int err = encode_base58(address_temp.address, + VERSION_SIZE + CX_RIPEMD160_SIZE + CHECKSUM_SIZE, + answer->address, &outLen); + if (err != 0) { + return zxerr_unknown; + } + *replyLen = PK_LEN_SECP256K1 + outLen; + return zxerr_ok; } zxerr_t crypto_fillSaplingSeed(uint8_t *sk) { - zemu_log_stack("crypto_fillSaplingSeed"); - - // Generate randomness using a fixed path related to the device mnemonic - const uint32_t path[HDPATH_LEN_DEFAULT] = { - 0x8000002c, - 0x80000085, - MASK_HARDENED, - MASK_HARDENED, - MASK_HARDENED, - }; - MEMZERO(sk, ED25519_SK_SIZE); + zemu_log_stack("crypto_fillSaplingSeed"); + + // Generate randomness using a fixed path related to the device mnemonic + const uint32_t path[HDPATH_LEN_DEFAULT] = { + 0x8000002c, 0x80000085, MASK_HARDENED, MASK_HARDENED, MASK_HARDENED, + }; + MEMZERO(sk, ED25519_SK_SIZE); - zxerr_t error = zxerr_unknown; - CATCH_CXERROR(os_derive_bip32_with_seed_no_throw(HDW_NORMAL, CX_CURVE_Ed25519, - path, HDPATH_LEN_DEFAULT, - sk, - NULL, - NULL, 0)) - error = zxerr_ok; + zxerr_t error = zxerr_unknown; + CATCH_CXERROR(os_derive_bip32_with_seed_no_throw(HDW_NORMAL, CX_CURVE_Ed25519, + path, HDPATH_LEN_DEFAULT, sk, + NULL, NULL, 0)) + error = zxerr_ok; catch_cx_error: - if (error != zxerr_ok) { - MEMZERO(sk, 64); - } + if (error != zxerr_ok) { + MEMZERO(sk, 64); + } - return error; + return error; } // handleInitTX step 1/2 -zxerr_t crypto_extracttx_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen) { - zemu_log_stack("crypto_extracttx_sapling"); - MEMZERO(buffer, bufferLen); - uint8_t t_in_len = *txdata; - uint8_t t_out_len = *(txdata + 1); - uint8_t spend_len = *(txdata + 2); - uint8_t output_len = *(txdata + 3); - - transaction_reset(); +zxerr_t crypto_extracttx_sapling(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint16_t txdatalen) { + zemu_log_stack("crypto_extracttx_sapling"); + MEMZERO(buffer, bufferLen); + uint8_t t_in_len = *txdata; + uint8_t t_out_len = *(txdata + 1); + uint8_t spend_len = *(txdata + 2); + uint8_t output_len = *(txdata + 3); + + transaction_reset(); + + if ((spend_len > 0 && output_len < 2) || + (spend_len == 0 && output_len == 1)) { + return (zxerr_t)EXTRACT_SAPLING_E0; + } + + if (txdatalen < 4 || txdatalen - 4 != t_in_len * T_IN_INPUT_LEN + + t_out_len * T_OUT_INPUT_LEN + + spend_len * SPEND_INPUT_LEN + + output_len * OUTPUT_INPUT_LEN) { + return (zxerr_t)EXTRACT_SAPLING_E1; + } + + if (t_in_len == 0 && t_out_len == 0 && spend_len == 0 && output_len == 0) { + return (zxerr_t)EXTRACT_SAPLING_E2; + } + + uint8_t *start = (uint8_t *)txdata; + start += 4; + + parser_context_t pars_ctx; + parser_error_t pars_err; + + for (int i = 0; i < t_in_len; i++) { + uint32_t *path = (uint32_t *)(start + INDEX_INPUT_TIN_PATH); + uint8_t *script = (uint8_t *)(start + INDEX_INPUT_TIN_SCRIPT); - if ((spend_len > 0 && output_len < 2) || (spend_len == 0 && output_len == 1)) { - return (zxerr_t) EXTRACT_SAPLING_E0; + pars_ctx.offset = 0; + pars_ctx.buffer = start + INDEX_INPUT_TIN_VALUE; + pars_ctx.bufferLen = 8; + uint64_t v = 0; + pars_err = _readUInt64(&pars_ctx, &v); + if (pars_err != parser_ok) { + return (zxerr_t)EXTRACT_SAPLING_E3; } - - if (txdatalen < 4 || txdatalen - 4 != - t_in_len * T_IN_INPUT_LEN + t_out_len * T_OUT_INPUT_LEN + spend_len * SPEND_INPUT_LEN + - output_len * OUTPUT_INPUT_LEN) { - return (zxerr_t) EXTRACT_SAPLING_E1; + zxerr_t err = t_inlist_append_item(path, script, v); + if (err != zxerr_ok) { + return (zxerr_t)EXTRACT_SAPLING_E4; } + start += T_IN_INPUT_LEN; + } - if (t_in_len == 0 && t_out_len == 0 && spend_len == 0 && output_len == 0) { - return (zxerr_t) EXTRACT_SAPLING_E2; + for (int i = 0; i < t_out_len; i++) { + uint8_t *addr = (uint8_t *)(start + INDEX_INPUT_TOUT_ADDR); + pars_ctx.offset = 0; + pars_ctx.buffer = start + INDEX_INPUT_TOUT_VALUE; + pars_ctx.bufferLen = 8; + uint64_t v = 0; + pars_err = _readUInt64(&pars_ctx, &v); + if (pars_err != parser_ok) { + return (zxerr_t)EXTRACT_SAPLING_E5; } - - uint8_t *start = (uint8_t *) txdata; - start += 4; - - parser_context_t pars_ctx; - parser_error_t pars_err; - - for (int i = 0; i < t_in_len; i++) { - uint32_t *path = (uint32_t * )(start + INDEX_INPUT_TIN_PATH); - uint8_t *script = (uint8_t * )(start + INDEX_INPUT_TIN_SCRIPT); - - pars_ctx.offset = 0; - pars_ctx.buffer = start + INDEX_INPUT_TIN_VALUE; - pars_ctx.bufferLen = 8; - uint64_t v = 0; - pars_err = _readUInt64(&pars_ctx, &v); - if (pars_err != parser_ok) { - return (zxerr_t) EXTRACT_SAPLING_E3; - } - zxerr_t err = t_inlist_append_item(path, script, v); - if (err != zxerr_ok) { - return (zxerr_t) EXTRACT_SAPLING_E4; - } - start += T_IN_INPUT_LEN; + zxerr_t err = t_outlist_append_item(addr, v); + if (err != zxerr_ok) { + return (zxerr_t)EXTRACT_SAPLING_E6; } + start += T_OUT_INPUT_LEN; + } - for (int i = 0; i < t_out_len; i++) { - uint8_t *addr = (uint8_t * )(start + INDEX_INPUT_TOUT_ADDR); - pars_ctx.offset = 0; - pars_ctx.buffer = start + INDEX_INPUT_TOUT_VALUE; - pars_ctx.bufferLen = 8; - uint64_t v = 0; - pars_err = _readUInt64(&pars_ctx, &v); - if (pars_err != parser_ok) { - return (zxerr_t) EXTRACT_SAPLING_E5; - } - zxerr_t err = t_outlist_append_item(addr, v); - if (err != zxerr_ok) { - return (zxerr_t) EXTRACT_SAPLING_E6; - } - start += T_OUT_INPUT_LEN; + for (int i = 0; i < spend_len; i++) { + pars_ctx.offset = 0; + pars_ctx.buffer = start + INDEX_INPUT_SPENDPOS; + pars_ctx.bufferLen = 4; + uint32_t p = 0; + pars_err = _readUInt32(&pars_ctx, &p); + if (pars_err != parser_ok) { + return (zxerr_t)EXTRACT_SAPLING_E7; } - for (int i = 0; i < spend_len; i++) { - pars_ctx.offset = 0; - pars_ctx.buffer = start + INDEX_INPUT_SPENDPOS; - pars_ctx.bufferLen = 4; - uint32_t p = 0; - pars_err = _readUInt32(&pars_ctx, &p); - if (pars_err != parser_ok) { - return (zxerr_t) EXTRACT_SAPLING_E7; - } - - pars_ctx.offset = 0; - pars_ctx.buffer = start + INDEX_INPUT_INPUTVALUE; - pars_ctx.bufferLen = 8; - uint64_t v = 0; - pars_err = _readUInt64(&pars_ctx, &v); - if (pars_err != parser_ok) { - return (zxerr_t) EXTRACT_SAPLING_E8; - } - - uint8_t *div = start + INDEX_INPUT_INPUTDIV; - uint8_t *pkd = start + INDEX_INPUT_INPUTPKD; - uint8_t rnd1[RND_SIZE]; - uint8_t rnd2[RND_SIZE]; - random_fr(rnd1); - random_fr(rnd2); - - zxerr_t err = spendlist_append_item(p, v, div, pkd, rnd1, rnd2); - if (err != zxerr_ok) { - return (zxerr_t) EXTRACT_SAPLING_E9; - } - start += SPEND_INPUT_LEN; + pars_ctx.offset = 0; + pars_ctx.buffer = start + INDEX_INPUT_INPUTVALUE; + pars_ctx.bufferLen = 8; + uint64_t v = 0; + pars_err = _readUInt64(&pars_ctx, &v); + if (pars_err != parser_ok) { + return (zxerr_t)EXTRACT_SAPLING_E8; } - for (int i = 0; i < output_len; i++) { - uint8_t *div = start + INDEX_INPUT_OUTPUTDIV; - uint8_t *pkd = start + INDEX_INPUT_OUTPUTPKD; - - pars_ctx.offset = 0; - pars_ctx.buffer = start + INDEX_INPUT_OUTPUTVALUE; - pars_ctx.bufferLen = 8; - uint64_t v = 0; - pars_err = _readUInt64(&pars_ctx, &v); - if (pars_err != parser_ok) { - return (zxerr_t) EXTRACT_SAPLING_EA; - } - - uint8_t *memotype = start + INDEX_INPUT_OUTPUTMEMO; - uint8_t *ovk = start + INDEX_INPUT_OUTPUTOVK; - if (ovk[0] != 0x00 && ovk[0] != 0x01) { - return (zxerr_t) EXTRACT_SAPLING_EB; - } - uint8_t hash_seed[OVK_SET_SIZE]; - if (ovk[0] == 0x00) { - MEMZERO(hash_seed, OVK_SET_SIZE); - cx_rng(hash_seed + 1, OVK_SIZE); - ovk = hash_seed; - } - - uint8_t rnd1[RND_SIZE]; - uint8_t rnd2[RND_SIZE]; - random_fr(rnd1); - cx_rng(rnd2, RND_SIZE); - zxerr_t err = outputlist_append_item(div, pkd, v, *memotype, ovk, rnd1, rnd2); - if (err != zxerr_ok) { - return (zxerr_t) EXTRACT_SAPLING_EC; - } - start += OUTPUT_INPUT_LEN; - } + uint8_t *div = start + INDEX_INPUT_INPUTDIV; + uint8_t *pkd = start + INDEX_INPUT_INPUTPKD; + uint8_t rnd1[RND_SIZE]; + uint8_t rnd2[RND_SIZE]; + random_fr(rnd1); + random_fr(rnd2); - uint64_t value_flash = get_totalvalue(); - if (value_flash != 1000) { - return (zxerr_t) EXTRACT_SAPLING_ED; + zxerr_t err = spendlist_append_item(p, v, div, pkd, rnd1, rnd2); + if (err != zxerr_ok) { + return (zxerr_t)EXTRACT_SAPLING_E9; } + start += SPEND_INPUT_LEN; + } - if (spend_len > 0) { - set_state(STATE_PROCESSED_INPUTS); //need both spend info and output info (as spend > 0 => output >= 2) - } else if (output_len > 0) { - set_state(STATE_PROCESSED_SPEND_EXTRACTIONS); //we can have shielded outputs only - } else { - set_state(STATE_PROCESSED_ALL_EXTRACTIONS); //We can have transparent inputs/outputs only - } + for (int i = 0; i < output_len; i++) { + uint8_t *div = start + INDEX_INPUT_OUTPUTDIV; + uint8_t *pkd = start + INDEX_INPUT_OUTPUTPKD; - return zxerr_ok; //some code for all_good + pars_ctx.offset = 0; + pars_ctx.buffer = start + INDEX_INPUT_OUTPUTVALUE; + pars_ctx.bufferLen = 8; + uint64_t v = 0; + pars_err = _readUInt64(&pars_ctx, &v); + if (pars_err != parser_ok) { + return (zxerr_t)EXTRACT_SAPLING_EA; + } + + uint8_t *memotype = start + INDEX_INPUT_OUTPUTMEMO; + uint8_t *ovk = start + INDEX_INPUT_OUTPUTOVK; + if (ovk[0] != 0x00 && ovk[0] != 0x01) { + return (zxerr_t)EXTRACT_SAPLING_EB; + } + uint8_t hash_seed[OVK_SET_SIZE]; + if (ovk[0] == 0x00) { + MEMZERO(hash_seed, OVK_SET_SIZE); + cx_rng(hash_seed + 1, OVK_SIZE); + ovk = hash_seed; + } + + uint8_t rnd1[RND_SIZE]; + uint8_t rnd2[RND_SIZE]; + random_fr(rnd1); + cx_rng(rnd2, RND_SIZE); + zxerr_t err = + outputlist_append_item(div, pkd, v, *memotype, ovk, rnd1, rnd2); + if (err != zxerr_ok) { + return (zxerr_t)EXTRACT_SAPLING_EC; + } + start += OUTPUT_INPUT_LEN; + } + + uint64_t value_flash = get_totalvalue(); + if (value_flash != 1000) { + return (zxerr_t)EXTRACT_SAPLING_ED; + } + + if (spend_len > 0) { + set_state(STATE_PROCESSED_INPUTS); // need both spend info and output info + // (as spend > 0 => output >= 2) + } else if (output_len > 0) { + set_state( + STATE_PROCESSED_SPEND_EXTRACTIONS); // we can have shielded outputs only + } else { + set_state(STATE_PROCESSED_ALL_EXTRACTIONS); // We can have transparent + // inputs/outputs only + } + + return zxerr_ok; // some code for all_good } - 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; - }; + 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; // handleExtractSpendData -zxerr_t crypto_extract_spend_proofkeyandrnd(uint8_t *buffer, uint16_t bufferLen){ - if(!spendlist_more_extract()){ - return zxerr_unknown; - } +zxerr_t crypto_extract_spend_proofkeyandrnd(uint8_t *buffer, + uint16_t bufferLen) { + if (!spendlist_more_extract()) { + return zxerr_unknown; + } - if(get_state() != STATE_PROCESSED_INPUTS){ - return zxerr_unknown; - } + if (get_state() != STATE_PROCESSED_INPUTS) { + return zxerr_unknown; + } - uint8_t *out = (uint8_t *) buffer; - MEMZERO(out, bufferLen); + uint8_t *out = (uint8_t *)buffer; + MEMZERO(out, bufferLen); - const spend_item_t *next = spendlist_extract_next(); - if (next == NULL){ - return zxerr_unknown; - } + const spend_item_t *next = spendlist_extract_next(); + if (next == NULL) { + return zxerr_unknown; + } - tmp_spendinfo_s tmp = {0}; + tmp_spendinfo_s tmp = {0}; - CHECK_ZXERROR_AND_CLEAN(crypto_fillSaplingSeed(tmp.step1.zip32_seed)) - CHECK_APP_CANARY() + CHECK_ZXERROR_AND_CLEAN(crypto_fillSaplingSeed(tmp.step1.zip32_seed)) + CHECK_APP_CANARY() - // Gets ak and nsk - zip32_child_proof_key(tmp.step1.zip32_seed, out, out + AK_SIZE, next->path); - CHECK_APP_CANARY() + // Gets ak and nsk + zip32_child_proof_key(tmp.step1.zip32_seed, out, out + AK_SIZE, next->path); + CHECK_APP_CANARY() - MEMZERO(&tmp, sizeof(tmp_spendinfo_s)); + 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); + 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_extract()){ - set_state(STATE_PROCESSED_SPEND_EXTRACTIONS); - } + if (!spendlist_more_extract()) { + set_state(STATE_PROCESSED_SPEND_EXTRACTIONS); + } - return zxerr_ok; + return zxerr_ok; } // handleExtractOutputData -zxerr_t crypto_extract_output_rnd(uint8_t *buffer, uint16_t bufferLen, uint16_t *replyLen){ - if(!outputlist_more_extract()){ - return zxerr_unknown; - } - - if(get_state() != STATE_PROCESSED_SPEND_EXTRACTIONS){ - return zxerr_unknown; - } - - uint8_t *out = (uint8_t *) buffer; - MEMZERO(out, bufferLen); - - const output_item_t *next = outputlist_extract_next(); - if (next == NULL){ - return zxerr_unknown; - } - MEMCPY(out, next->rcmvalue, RCM_V_SIZE); - MEMCPY(out+RCM_V_SIZE, next->rseed, RSEED_SIZE); - - if(next->ovk[0] == 0x00){ - MEMCPY(out+RCM_V_SIZE + RSEED_SIZE, next->ovk + 1, OVK_SIZE); - *replyLen = RCM_V_SIZE + RSEED_SIZE + OVK_SIZE; - }else{ - *replyLen = RCM_V_SIZE + RSEED_SIZE; - } - - if(!outputlist_more_extract()){ - set_state(STATE_PROCESSED_ALL_EXTRACTIONS); - } - return zxerr_ok; +zxerr_t crypto_extract_output_rnd(uint8_t *buffer, uint16_t bufferLen, + uint16_t *replyLen) { + if (!outputlist_more_extract()) { + return zxerr_unknown; + } + + if (get_state() != STATE_PROCESSED_SPEND_EXTRACTIONS) { + return zxerr_unknown; + } + + uint8_t *out = (uint8_t *)buffer; + MEMZERO(out, bufferLen); + + const output_item_t *next = outputlist_extract_next(); + if (next == NULL) { + return zxerr_unknown; + } + MEMCPY(out, next->rcmvalue, RCM_V_SIZE); + MEMCPY(out + RCM_V_SIZE, next->rseed, RSEED_SIZE); + + if (next->ovk[0] == 0x00) { + MEMCPY(out + RCM_V_SIZE + RSEED_SIZE, next->ovk + 1, OVK_SIZE); + *replyLen = RCM_V_SIZE + RSEED_SIZE + OVK_SIZE; + } else { + *replyLen = RCM_V_SIZE + RSEED_SIZE; + } + + if (!outputlist_more_extract()) { + set_state(STATE_PROCESSED_ALL_EXTRACTIONS); + } + return zxerr_ok; } // handleCheckandSign step 1/11 -zxerr_t crypto_check_prevouts(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint8_t tx_version){ - zemu_log_stack("crypto_check_prevouts"); - MEMZERO(buffer, bufferLen); - - if(get_state() != STATE_CHECKING_ALL_TXDATA){ - return zxerr_unknown; - } - - uint8_t hash[HASH_SIZE] = {0}; - size_t prevouts_hash_offset = 0; - if (tx_version == TX_VERSION_SAPLING) { - sapling_transparent_prevouts_hash(txdata, hash); - prevouts_hash_offset = SAPLING_INDEX_HASH_PREVOUTSHASH; - } else if (tx_version == TX_VERSION_NU5){ - nu5_transparent_prevouts_hash(txdata,hash); - prevouts_hash_offset = NU5_INDEX_HASH_PREVOUTSHASH; - } else { - return zxerr_unknown; - } - - if(MEMCMP(hash, txdata + start_sighashdata() + prevouts_hash_offset, HASH_SIZE) != 0){ - return zxerr_unknown; - } - return zxerr_ok; +zxerr_t crypto_check_prevouts(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, const uint8_t tx_version) { + zemu_log_stack("crypto_check_prevouts"); + MEMZERO(buffer, bufferLen); + + if (get_state() != STATE_CHECKING_ALL_TXDATA) { + return zxerr_unknown; + } + + uint8_t hash[HASH_SIZE] = {0}; + size_t prevouts_hash_offset = 0; + if (tx_version == TX_VERSION_SAPLING) { + sapling_transparent_prevouts_hash(txdata, hash); + prevouts_hash_offset = SAPLING_INDEX_HASH_PREVOUTSHASH; + } else if (tx_version == TX_VERSION_NU5) { + nu5_transparent_prevouts_hash(txdata, hash); + prevouts_hash_offset = NU5_INDEX_HASH_PREVOUTSHASH; + } else { + return zxerr_unknown; + } + + if (MEMCMP(hash, txdata + start_sighashdata() + prevouts_hash_offset, + HASH_SIZE) != 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, const uint8_t tx_version){ - zemu_log_stack("crypto_check_sequence"); - MEMZERO(buffer, bufferLen); - - if(get_state() != STATE_CHECKING_ALL_TXDATA){ - return zxerr_unknown; - } - - uint8_t hash[HASH_SIZE] = {0}; - size_t sequence_hash_offset = 0; - - if (tx_version==TX_VERSION_SAPLING) { - sapling_transparent_sequence_hash(txdata, hash); - sequence_hash_offset = SAPLING_INDEX_HASH_SEQUENCEHASH; - } - else if (tx_version == TX_VERSION_NU5){ - nu5_transparent_sequence_hash(txdata,hash); - sequence_hash_offset = NU5_INDEX_HASH_SEQUENCEHASH; - } - else { - return zxerr_unknown; - } - - if(MEMCMP(hash, txdata + start_sighashdata() + sequence_hash_offset, HASH_SIZE) != 0){ - return zxerr_unknown; - } - return zxerr_ok; +zxerr_t crypto_check_sequence(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, const uint8_t tx_version) { + zemu_log_stack("crypto_check_sequence"); + MEMZERO(buffer, bufferLen); + + if (get_state() != STATE_CHECKING_ALL_TXDATA) { + return zxerr_unknown; + } + + uint8_t hash[HASH_SIZE] = {0}; + size_t sequence_hash_offset = 0; + + if (tx_version == TX_VERSION_SAPLING) { + sapling_transparent_sequence_hash(txdata, hash); + sequence_hash_offset = SAPLING_INDEX_HASH_SEQUENCEHASH; + } else if (tx_version == TX_VERSION_NU5) { + nu5_transparent_sequence_hash(txdata, hash); + sequence_hash_offset = NU5_INDEX_HASH_SEQUENCEHASH; + } else { + return zxerr_unknown; + } + + if (MEMCMP(hash, txdata + start_sighashdata() + sequence_hash_offset, + HASH_SIZE) != 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, const uint8_t tx_version){ - 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_SIZE] = {0}; - size_t sapling_outputs_hash_offset = 0; - - if (tx_version==TX_VERSION_SAPLING) { - v4_transparent_outputs_hash(hash); - sapling_outputs_hash_offset = SAPLING_INDEX_HASH_OUTPUTSHASH; - } - else if (tx_version == TX_VERSION_NU5){ - nu5_transparent_outputs_hash(hash); - sapling_outputs_hash_offset = NU5_INDEX_HASH_OUTPUTSHASH; - } - else - { - return zxerr_unknown; - } - - if(MEMCMP(hash, txdata + start_sighashdata() + sapling_outputs_hash_offset, HASH_SIZE) != 0){ - return zxerr_unknown; - } - return zxerr_ok; +zxerr_t crypto_check_outputs(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, const uint16_t txdatalen, + const uint8_t tx_version) { + 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_SIZE] = {0}; + size_t sapling_outputs_hash_offset = 0; + + if (tx_version == TX_VERSION_SAPLING) { + v4_transparent_outputs_hash(hash); + sapling_outputs_hash_offset = SAPLING_INDEX_HASH_OUTPUTSHASH; + } else if (tx_version == TX_VERSION_NU5) { + nu5_transparent_outputs_hash(hash); + sapling_outputs_hash_offset = NU5_INDEX_HASH_OUTPUTSHASH; + } else { + return zxerr_unknown; + } + + if (MEMCMP(hash, txdata + start_sighashdata() + sapling_outputs_hash_offset, + HASH_SIZE) != 0) { + return zxerr_unknown; + } + return zxerr_ok; } // handleCheckandSign step 4/11 -zxerr_t crypto_check_joinsplits(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint8_t tx_version){ - if (tx_version == TX_VERSION_SAPLING){ - zemu_log_stack("crypto_check_joinsplits"); - MEMZERO(buffer, bufferLen); - - if(get_state() != STATE_CHECKING_ALL_TXDATA){ - return zxerr_unknown; - } +zxerr_t crypto_check_joinsplits(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint8_t tx_version) { + if (tx_version == TX_VERSION_SAPLING) { + zemu_log_stack("crypto_check_joinsplits"); + MEMZERO(buffer, bufferLen); - uint8_t hash[HASH_SIZE] = {0}; - if(MEMCMP(hash, txdata + start_sighashdata() + SAPLING_INDEX_HASH_JOINSPLITSHASH, HASH_SIZE) != 0){ - return zxerr_unknown; - } + if (get_state() != STATE_CHECKING_ALL_TXDATA) { + return zxerr_unknown; + } + uint8_t hash[HASH_SIZE] = {0}; + if (MEMCMP(hash, + txdata + start_sighashdata() + SAPLING_INDEX_HASH_JOINSPLITSHASH, + HASH_SIZE) != 0) { + return zxerr_unknown; } - return zxerr_ok; + } + return zxerr_ok; } // handleCheckandSign step 5/11 -zxerr_t crypto_check_valuebalance(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint8_t tx_version){ - zemu_log_stack("crypto_check_valuebalance"); - MEMZERO(buffer, bufferLen); - - if(get_state() != STATE_CHECKING_ALL_TXDATA){ - return zxerr_unknown; - } - parser_context_t pars_ctx; - parser_error_t pars_err; - size_t value_balance_offset = 0; - if (tx_version==TX_VERSION_SAPLING) { - value_balance_offset = SAPLING_INDEX_HASH_VALUEBALANCE; - } - else if (tx_version == TX_VERSION_NU5){ - value_balance_offset = NU5_INDEX_HASH_VALUEBALANCE; - } - else { - return zxerr_unknown; - } - pars_ctx.offset = 0; - pars_ctx.buffer = txdata + start_sighashdata() + value_balance_offset; - pars_ctx.bufferLen = 8; - int64_t v = 0; - pars_err = _readInt64(&pars_ctx, &v); - if (pars_err != parser_ok){ - return 0; - } - - int64_t valuebalance = get_valuebalance(); - int64_t *value_flash = (int64_t *)&valuebalance; - if(MEMCMP(&v, value_flash, 8) != 0){ - return zxerr_unknown; - } - return zxerr_ok; +zxerr_t crypto_check_valuebalance(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint8_t tx_version) { + zemu_log_stack("crypto_check_valuebalance"); + MEMZERO(buffer, bufferLen); + + if (get_state() != STATE_CHECKING_ALL_TXDATA) { + return zxerr_unknown; + } + parser_context_t pars_ctx; + parser_error_t pars_err; + size_t value_balance_offset = 0; + if (tx_version == TX_VERSION_SAPLING) { + value_balance_offset = SAPLING_INDEX_HASH_VALUEBALANCE; + } else if (tx_version == TX_VERSION_NU5) { + value_balance_offset = NU5_INDEX_HASH_VALUEBALANCE; + } else { + return zxerr_unknown; + } + pars_ctx.offset = 0; + pars_ctx.buffer = txdata + start_sighashdata() + value_balance_offset; + pars_ctx.bufferLen = 8; + int64_t v = 0; + pars_err = _readInt64(&pars_ctx, &v); + if (pars_err != parser_ok) { + return 0; + } + + int64_t valuebalance = get_valuebalance(); + int64_t *value_flash = (int64_t *)&valuebalance; + if (MEMCMP(&v, value_flash, 8) != 0) { + return zxerr_unknown; + } + return zxerr_ok; } typedef struct { - union { - struct { - uint8_t pedersen_input[PEDERSEN_INPUT_SIZE]; - }; - struct { - uint8_t pedersen_hash[HASH_SIZE]; - }; - - struct { - uint8_t ncm_full[NOTE_COMMITMENT_SIZE]; - }; - struct { - uint8_t nf[NULLIFIER_SIZE]; - }; - - struct { - uint8_t spend_hash[HASH_SIZE]; - }; + union { + struct { + uint8_t pedersen_input[PEDERSEN_INPUT_SIZE]; + }; + struct { + uint8_t pedersen_hash[HASH_SIZE]; + }; + + struct { + uint8_t ncm_full[NOTE_COMMITMENT_SIZE]; + }; + struct { + uint8_t nf[NULLIFIER_SIZE]; + }; + + struct { + uint8_t spend_hash[HASH_SIZE]; }; + }; } tmp_buf_checkspend; typedef struct { - union { - // STEP 1 - struct { - uint8_t zip32_seed[ZIP32_SEED_SIZE]; - } step1; - - struct { - uint8_t ask[ASK_SIZE]; - uint8_t nsk[NSK_SIZE]; - } step2; - - struct { - uint8_t rk[PUB_KEY_SIZE]; - uint8_t nsk[NSK_SIZE]; - } step3; - - struct { - uint8_t cv[VALUE_COMMITMENT_SIZE]; - uint8_t nsk[NSK_SIZE]; - } step4; - }; + union { + // STEP 1 + struct { + uint8_t zip32_seed[ZIP32_SEED_SIZE]; + } step1; + + struct { + uint8_t ask[ASK_SIZE]; + uint8_t nsk[NSK_SIZE]; + } step2; + + struct { + uint8_t rk[PUB_KEY_SIZE]; + uint8_t nsk[NSK_SIZE]; + } step3; + + struct { + uint8_t cv[VALUE_COMMITMENT_SIZE]; + uint8_t nsk[NSK_SIZE]; + } step4; + }; } tmp_checkspend; // handleCheckandSign step 6/11 -zxerr_t crypto_checkspend_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen, const uint8_t tx_version) { - zemu_log_stack("crypto_checkspend_sapling"); - MEMZERO(buffer, bufferLen); +zxerr_t crypto_checkspend_sapling(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint16_t txdatalen, + const uint8_t tx_version) { + zemu_log_stack("crypto_checkspend_sapling"); + MEMZERO(buffer, bufferLen); - const size_t length_hash_data = (tx_version == TX_VERSION_SAPLING) ? SAPLING_LENGTH_HASH_DATA : NU5_LENGTH_HASH_DATA; + const size_t length_hash_data = (tx_version == TX_VERSION_SAPLING) + ? SAPLING_LENGTH_HASH_DATA + : NU5_LENGTH_HASH_DATA; - if(length_t_in_data() + length_spenddata() + length_outputdata() + length_hash_data != txdatalen){ - return zxerr_unknown; - } + if (length_t_in_data() + length_spenddata() + length_outputdata() + + length_hash_data != + txdatalen) { + return zxerr_unknown; + } - if(get_state() != STATE_CHECKING_ALL_TXDATA){ - return zxerr_unknown; + if (get_state() != STATE_CHECKING_ALL_TXDATA) { + return zxerr_unknown; + } + + uint8_t *out = buffer; + tmp_buf_checkspend *const tmp_buf = (tmp_buf_checkspend *)buffer; + + uint8_t *start_spenddata = + (uint8_t *)(txdata + length_t_in_data() + length_spend_old_data()); + uint8_t *start_spendolddata = (uint8_t *)(txdata + length_t_in_data()); + + tmp_checkspend tmp = {0}; + + // the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last + // part of hdPath + const uint8_t spendListSize = spendlist_len(); + + for (uint8_t i = 0; i < spendListSize; i++) { + CHECK_ZXERROR_AND_CLEAN(crypto_fillSaplingSeed(tmp.step1.zip32_seed)) + const spend_item_t *item = spendlist_retrieve_item(i); + if (item == NULL) { + return zxerr_unknown; } - uint8_t *out = buffer; - tmp_buf_checkspend *const tmp_buf = (tmp_buf_checkspend *) buffer; - - uint8_t *start_spenddata = (uint8_t *)(txdata + length_t_in_data() + length_spend_old_data()); - uint8_t *start_spendolddata = (uint8_t *)(txdata + length_t_in_data()); - - tmp_checkspend tmp = {0}; - - //the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last part of hdPath - const uint8_t spendListSize = spendlist_len(); - - for(uint8_t i = 0; i < spendListSize; i++) { - CHECK_ZXERROR_AND_CLEAN(crypto_fillSaplingSeed(tmp.step1.zip32_seed)) - const spend_item_t *item = spendlist_retrieve_item(i); - if (item == NULL) { - return zxerr_unknown; - } - - // we later need nsk - zip32_child_ask_nsk(tmp.step1.zip32_seed, tmp.step2.ask, tmp.step2.nsk, item->path); - get_rk(tmp.step2.ask, (uint8_t *)item->alpha, tmp.step3.rk); - if(MEMCMP(tmp.step3.rk, start_spenddata + INDEX_SPEND_RK + i * SPEND_TX_LEN,PUB_KEY_SIZE) != 0){ - CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) - } - - // step4.cv = step3.rk. - compute_value_commitment(item->value, item->rcmvalue,tmp.step4.cv); - if (MEMCMP(tmp.step4.cv, start_spenddata + INDEX_SPEND_VALUECMT + i *SPEND_TX_LEN,VALUE_COMMITMENT_SIZE) != 0){ - CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) - } - - compute_note_commitment_fullpoint(tmp_buf->pedersen_hash, start_spendolddata + INDEX_SPEND_OLD_RCM + i * SPEND_OLD_TX_LEN,item->value, item->div, item->pkd); - - uint64_t notepos = 0; - { - parser_context_t pars_ctx; - parser_error_t pars_err; - - pars_ctx.offset = 0; - pars_ctx.buffer = start_spendolddata + INDEX_SPEND_OLD_NOTEPOS + i * SPEND_OLD_TX_LEN; - pars_ctx.bufferLen = 8; - pars_err = _readUInt64(&pars_ctx, ¬epos); - if (pars_err != parser_ok){ - CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) - } - } - compute_nullifier(tmp_buf->ncm_full, notepos, tmp.step4.nsk, tmp_buf->nf); - if (MEMCMP(tmp_buf->nf, start_spenddata + INDEX_SPEND_NF + i * SPEND_TX_LEN, NULLIFIER_SIZE) != 0){ - CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) - } - - MEMZERO(out, bufferLen); - MEMZERO(&tmp, sizeof(tmp_checkspend)); + // we later need nsk + zip32_child_ask_nsk(tmp.step1.zip32_seed, tmp.step2.ask, tmp.step2.nsk, + item->path); + get_rk(tmp.step2.ask, (uint8_t *)item->alpha, tmp.step3.rk); + if (MEMCMP(tmp.step3.rk, + start_spenddata + INDEX_SPEND_RK + i * SPEND_TX_LEN, + PUB_KEY_SIZE) != 0) { + CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) } - size_t sapling_spend_offset = 0; - if (tx_version == TX_VERSION_SAPLING) { - if (spendlist_len() > 0) { - shielded_spend_hash(start_spenddata, length_spend_new_data(), tmp_buf->spend_hash); - } - sapling_spend_offset = SAPLING_INDEX_HASH_SHIELDEDSPENDHASH; - } else if (tx_version == TX_VERSION_NU5) { - nu5_hash_sapling_spends(start_spenddata, tmp_buf->spend_hash); - sapling_spend_offset = NU5_INDEX_HASH_SHIELDEDSPENDHASH; - } else { - CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) + // step4.cv = step3.rk. + compute_value_commitment(item->value, item->rcmvalue, tmp.step4.cv); + if (MEMCMP(tmp.step4.cv, + start_spenddata + INDEX_SPEND_VALUECMT + i * SPEND_TX_LEN, + VALUE_COMMITMENT_SIZE) != 0) { + CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) } - if(MEMCMP(tmp_buf->spend_hash, txdata + start_sighashdata() + sapling_spend_offset, HASH_SIZE) != 0){ + compute_note_commitment_fullpoint(tmp_buf->pedersen_hash, + start_spendolddata + INDEX_SPEND_OLD_RCM + + i * SPEND_OLD_TX_LEN, + item->value, item->div, item->pkd); + + uint64_t notepos = 0; + { + parser_context_t pars_ctx; + parser_error_t pars_err; + + pars_ctx.offset = 0; + pars_ctx.buffer = + start_spendolddata + INDEX_SPEND_OLD_NOTEPOS + i * SPEND_OLD_TX_LEN; + pars_ctx.bufferLen = 8; + pars_err = _readUInt64(&pars_ctx, ¬epos); + if (pars_err != parser_ok) { CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) + } + } + compute_nullifier(tmp_buf->ncm_full, notepos, tmp.step4.nsk, tmp_buf->nf); + if (MEMCMP(tmp_buf->nf, start_spenddata + INDEX_SPEND_NF + i * SPEND_TX_LEN, + NULLIFIER_SIZE) != 0) { + CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) } - MEMZERO(out,bufferLen); - return zxerr_ok; //or some code for ok + MEMZERO(out, bufferLen); + MEMZERO(&tmp, sizeof(tmp_checkspend)); + } + + size_t sapling_spend_offset = 0; + if (tx_version == TX_VERSION_SAPLING) { + if (spendlist_len() > 0) { + shielded_spend_hash(start_spenddata, length_spend_new_data(), + tmp_buf->spend_hash); + } + sapling_spend_offset = SAPLING_INDEX_HASH_SHIELDEDSPENDHASH; + } else if (tx_version == TX_VERSION_NU5) { + nu5_hash_sapling_spends(start_spenddata, tmp_buf->spend_hash); + sapling_spend_offset = NU5_INDEX_HASH_SHIELDEDSPENDHASH; + } else { + CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) + } + + if (MEMCMP(tmp_buf->spend_hash, + txdata + start_sighashdata() + sapling_spend_offset, + HASH_SIZE) != 0) { + CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) + } + MEMZERO(out, bufferLen); + + return zxerr_ok; // or some code for ok } typedef struct { - uint8_t shielded_output_hash[HASH_SIZE]; + uint8_t shielded_output_hash[HASH_SIZE]; } tmp_buf_checkoutput; typedef struct { - union { - struct { - uint8_t gd[GD_SIZE]; //computed from receiver diversifier - uint8_t pkd[PKD_SIZE]; //get this from host and show on screen for verification - } step2; - - struct { - uint8_t pedersen_input[PEDERSEN_INPUT_SIZE]; - } step3; - - struct{ - uint8_t notecommitment[NOTE_COMMITMENT_SIZE]; - uint8_t valuecommitment[VALUE_COMMITMENT_SIZE]; - } step4; - }; + union { + struct { + uint8_t gd[GD_SIZE]; // computed from receiver diversifier + uint8_t pkd[PKD_SIZE]; // get this from host and show on screen for + // verification + } step2; + + struct { + uint8_t pedersen_input[PEDERSEN_INPUT_SIZE]; + } step3; + + struct { + uint8_t notecommitment[NOTE_COMMITMENT_SIZE]; + uint8_t valuecommitment[VALUE_COMMITMENT_SIZE]; + } step4; + }; } tmp_checkoutput; // handleCheckandSign step 7/11 -zxerr_t crypto_checkoutput_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen, const uint8_t tx_version) { - zemu_log_stack("crypto_checkoutput_sapling"); - MEMZERO(buffer, bufferLen); - - if (get_state() != STATE_CHECKING_ALL_TXDATA) { - return zxerr_unknown; - } - - const size_t length_hash_data = (tx_version == TX_VERSION_SAPLING) ? SAPLING_LENGTH_HASH_DATA : NU5_LENGTH_HASH_DATA; - if (length_t_in_data() + length_spenddata() + length_outputdata() + length_hash_data != txdatalen) { - return zxerr_unknown; - } - - const uint8_t *start_outputdata = (uint8_t *) (txdata + length_t_in_data() + length_spenddata()); - - zemu_log_stack("crypto_checkoutput_sapling"); - - tmp_checkoutput ncm = {0}; - - uint8_t rcm[RCM_SIZE] = {0}; - - //the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last part of hdPath - const uint8_t outputListLen = outputlist_len(); - for(uint8_t i = 0; i < outputListLen; i++) { - const output_item_t *item = outputlist_retrieve_item(i); - if (item == NULL) { - MEMZERO(&ncm, sizeof(tmp_checkoutput)); - return zxerr_unknown; - } - - rseed_get_rcm(item->rseed,rcm); - compute_note_commitment(ncm.step4.notecommitment,rcm,item->value, item->div, item->pkd); - compute_value_commitment(item->value, item->rcmvalue, ncm.step4.valuecommitment); +zxerr_t crypto_checkoutput_sapling(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint16_t txdatalen, + const uint8_t tx_version) { + zemu_log_stack("crypto_checkoutput_sapling"); + MEMZERO(buffer, bufferLen); + + if (get_state() != STATE_CHECKING_ALL_TXDATA) { + return zxerr_unknown; + } + + const size_t length_hash_data = (tx_version == TX_VERSION_SAPLING) + ? SAPLING_LENGTH_HASH_DATA + : NU5_LENGTH_HASH_DATA; + if (length_t_in_data() + length_spenddata() + length_outputdata() + + length_hash_data != + txdatalen) { + return zxerr_unknown; + } + + const uint8_t *start_outputdata = + (uint8_t *)(txdata + length_t_in_data() + length_spenddata()); + + zemu_log_stack("crypto_checkoutput_sapling"); + + tmp_checkoutput ncm = {0}; + + uint8_t rcm[RCM_SIZE] = {0}; + + // the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last + // part of hdPath + const uint8_t outputListLen = outputlist_len(); + for (uint8_t i = 0; i < outputListLen; i++) { + const output_item_t *item = outputlist_retrieve_item(i); + if (item == NULL) { + MEMZERO(&ncm, sizeof(tmp_checkoutput)); + return zxerr_unknown; + } + + rseed_get_rcm(item->rseed, rcm); + compute_note_commitment(ncm.step4.notecommitment, rcm, item->value, + item->div, item->pkd); + compute_value_commitment(item->value, item->rcmvalue, + ncm.step4.valuecommitment); + + if (MEMCMP(ncm.step4.valuecommitment, + start_outputdata + INDEX_OUTPUT_VALUECMT + i * OUTPUT_TX_LEN, + VALUE_COMMITMENT_SIZE) != 0) { + MEMZERO(&ncm, sizeof(tmp_checkoutput)); + return zxerr_unknown; + } + + if (MEMCMP(ncm.step4.notecommitment, + start_outputdata + INDEX_OUTPUT_NOTECMT + i * OUTPUT_TX_LEN, + NOTE_COMMITMENT_SIZE) != 0) { + MEMZERO(&ncm, sizeof(tmp_checkoutput)); + return zxerr_unknown; + } + + MEMZERO(&ncm, sizeof(tmp_checkoutput)); + } + + tmp_buf_checkoutput *const tmp_buf = (tmp_buf_checkoutput *)buffer; + + size_t sapling_output_offset = 0; + if (tx_version == TX_VERSION_SAPLING) { + if (outputlist_len() > 0) { + shielded_output_hash(start_outputdata, length_outputdata(), + tmp_buf->shielded_output_hash); + } + sapling_output_offset = SAPLING_INDEX_HASH_SHIELDEDOUTPUTHASH; + } else if (tx_version == TX_VERSION_NU5) { + nu5_hash_sapling_outputs(start_outputdata, tmp_buf->shielded_output_hash); + sapling_output_offset = NU5_INDEX_HASH_SHIELDEDOUTPUTHASH; + } else { + return zxerr_unknown; + } + + if (MEMCMP(tmp_buf->shielded_output_hash, + txdata + start_sighashdata() + sapling_output_offset, + HASH_SIZE) != 0) { + return zxerr_unknown; + } + + return zxerr_ok; // or some code for ok +} - if (MEMCMP(ncm.step4.valuecommitment, start_outputdata + INDEX_OUTPUT_VALUECMT + i * OUTPUT_TX_LEN,VALUE_COMMITMENT_SIZE) != 0){ - MEMZERO(&ncm, sizeof(tmp_checkoutput)); - return zxerr_unknown; - } +typedef struct { + union { + // STEP 1 + struct { // MAX SIZE --> 160 + uint8_t dummy[MAX_SIZE - EPK_SIZE - ESK_SIZE]; + uint8_t epk[EPK_SIZE]; // computed from receiver diversifier + uint8_t esk[ESK_SIZE]; + } step1; + + struct { + uint8_t chachanonce[CHACHA_NONCE_SIZE]; + uint8_t compactout[COMPACT_OUT_SIZE]; + uint8_t sharedkey[SHARED_KEY_SIZE]; + uint8_t epk[EPK_SIZE]; + uint8_t esk[ESK_SIZE]; + } step2; + + struct { + uint8_t dummy[MAX_SIZE - OVK_SIZE - VALUE_COMMITMENT_SIZE - + NOTE_COMMITMENT_SIZE - EPK_SIZE - ESK_SIZE]; + uint8_t ovk[OVK_SIZE]; + uint8_t valuecmt[VALUE_COMMITMENT_SIZE]; + uint8_t notecmt[NOTE_COMMITMENT_SIZE]; + uint8_t epk[EPK_SIZE]; + uint8_t esk[ESK_SIZE]; + } step3; + + struct { + uint8_t dummy[MAX_SIZE - PRF_INPUT_SIZE - ESK_SIZE]; + uint8_t prfinput[PRF_INPUT_SIZE]; + uint8_t esk[ESK_SIZE]; + } step4; + + struct { + uint8_t outkey[OUT_KEY_SIZE]; + uint8_t dummy[MAX_SIZE - OUT_KEY_SIZE - PKD_SIZE - ESK_SIZE]; + uint8_t pkd[PKD_SIZE]; + uint8_t esk[ESK_SIZE]; + } step5; + + struct { + uint8_t outkey[OUT_KEY_SIZE]; + uint8_t + dummy[MAX_SIZE - OUT_KEY_SIZE - ENC_CIPHER_SIZE - CHACHA_NONCE_SIZE]; + uint8_t chachanonce[CHACHA_NONCE_SIZE]; + uint8_t encciph[ENC_CIPHER_SIZE]; + } step6; + + struct { + uint8_t hashseed[OVK_SET_SIZE]; + uint8_t outkey[OUT_KEY_SIZE]; + uint8_t encciph_part1[ENC_CIPHER_HALVE_SIZE]; + uint8_t encciph_part2[ENC_CIPHER_HALVE_SIZE]; + uint8_t chachanonce[CHACHA_NONCE_SIZE]; + } step3b; + struct { + uint8_t hashseed[OVK_SET_SIZE]; + uint8_t outkey[OUT_KEY_SIZE]; + uint8_t encciph[ENC_CIPHER_SIZE]; + uint8_t chachanonce[CHACHA_NONCE_SIZE]; + } step4b; + }; +} tmp_enc; - if(MEMCMP(ncm.step4.notecommitment, start_outputdata + INDEX_OUTPUT_NOTECMT + i * OUTPUT_TX_LEN,NOTE_COMMITMENT_SIZE) != 0){ - MEMZERO(&ncm, sizeof(tmp_checkoutput)); - return zxerr_unknown; - } +// handleCheckandSign step 8/11 +zxerr_t crypto_checkencryptions_sapling(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata) { + zemu_log_stack("crypto_checkencryptions_sapling"); + MEMZERO(buffer, bufferLen); + tmp_enc *tmp = (tmp_enc *)buffer; + + const uint8_t *start_outputdata = + (uint8_t *)(txdata + length_t_in_data() + length_spenddata()); + + // the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last + // part of hdPath + for (uint8_t i = 0; i < outputlist_len(); i++) { + // retrieve info on list of outputs stored in flash + const output_item_t *item = outputlist_retrieve_item(i); + if (item == NULL) { + return zxerr_unknown; + } + // compute random ephemeral private and public keys (esk,epk) from seed and + // diversifier + rseed_get_esk_epk(item->rseed, (uint8_t *)item->div, tmp->step1.esk, + tmp->step1.epk); + CHECK_APP_CANARY() - MEMZERO(&ncm, sizeof(tmp_checkoutput)); + // compare the computed epk to that provided in the transaction data + if (MEMCMP(tmp->step1.epk, + start_outputdata + INDEX_OUTPUT_EPK + i * OUTPUT_TX_LEN, + EPK_SIZE) != 0) { + return zxerr_unknown; } - tmp_buf_checkoutput *const tmp_buf = (tmp_buf_checkoutput *) buffer; - - size_t sapling_output_offset = 0; - if (tx_version==TX_VERSION_SAPLING) { - if (outputlist_len() > 0) { - shielded_output_hash(start_outputdata, length_outputdata(), tmp_buf->shielded_output_hash); - } - sapling_output_offset = SAPLING_INDEX_HASH_SHIELDEDOUTPUTHASH; - } else if (tx_version == TX_VERSION_NU5) { - nu5_hash_sapling_outputs(start_outputdata, tmp_buf->shielded_output_hash); - sapling_output_offset = NU5_INDEX_HASH_SHIELDEDOUTPUTHASH; - } else { + // get shared key (used as encryption key) from esk, epk and pkd + ka_to_key(tmp->step1.esk, (uint8_t *)item->pkd, tmp->step1.epk, + tmp->step2.sharedkey); + CHECK_APP_CANARY() + // encode (div, value rseed and memotype) into step2.compactout ready to be + // encrypted + prepare_enccompact_input((uint8_t *)item->div, item->value, + (uint8_t *)item->rseed, item->memotype, + tmp->step2.compactout); + CHECK_APP_CANARY() + MEMZERO(tmp->step2.chachanonce, CHACHA_NONCE_SIZE); + // encrypt the previously obtained encoding, and store it in + // step2.compactoutput (reusing the same memory for input and output) + chacha(tmp->step2.compactout, tmp->step2.compactout, COMPACT_OUT_SIZE, + tmp->step2.sharedkey, tmp->step2.chachanonce, 1); + CHECK_APP_CANARY() + // check that the computed encryption is the same as that provided in the + // transaction data + if (MEMCMP(tmp->step2.compactout, + start_outputdata + INDEX_OUTPUT_ENC + i * OUTPUT_TX_LEN, + COMPACT_OUT_SIZE) != 0) { + return zxerr_unknown; + } + + // if an ovk was provided + if (item->ovk[0] != 0x00) { + // copy ovk, the value commitment and note-commitment from flash memory + // and transaction to local tmp structure so as to hash + MEMCPY(tmp->step3.ovk, item->ovk + 1, OVK_SIZE); + MEMCPY(tmp->step3.valuecmt, + start_outputdata + INDEX_OUTPUT_VALUECMT + i * OUTPUT_TX_LEN, + VALUE_COMMITMENT_SIZE); + MEMCPY(tmp->step3.notecmt, + start_outputdata + INDEX_OUTPUT_NOTECMT + i * OUTPUT_TX_LEN, + NOTE_COMMITMENT_SIZE); + // Note that tmp->step4.prfinput is the same memory chunk as the + // concatenation of tmp->step3.ovk || tmp->step3.valuecmt || + // tmp->step3.notecmt || tmp->step3.epk so next we hash that + // concatenation, and store hash in tmp->step5.outkey + blake2b_prf(tmp->step4.prfinput, tmp->step5.outkey); + CHECK_APP_CANARY() + + // get pkd from flash memory, store it in tmp->step5.pkd + MEMCPY(tmp->step5.pkd, item->pkd, PKD_SIZE); + + MEMZERO(tmp->step6.chachanonce, CHACHA_NONCE_SIZE); + + // tmp->step6.encciph = tmp->step5.pkd || tmp->step5.esk + // encrypt that, using as encryption key the output of the blake2b PRF + // store resulting ciphertext in tmp->step6.encciph + chacha(tmp->step6.encciph, tmp->step6.encciph, ENC_CIPHER_SIZE, + tmp->step6.outkey, tmp->step6.chachanonce, 1); + CHECK_APP_CANARY() + + // check that the computed encryption is the same as that provided in the + // transaction data + if (MEMCMP(tmp->step6.encciph, + start_outputdata + INDEX_OUTPUT_OUT + i * OUTPUT_TX_LEN, + ENC_CIPHER_SIZE) != 0) { return zxerr_unknown; - } + } - if(MEMCMP(tmp_buf->shielded_output_hash, txdata + start_sighashdata() + sapling_output_offset, HASH_SIZE) != 0){ + // if no ovk was provided + } else { + // copy the contents of flash memory for ovk, and hash it. This hash will + // be the encryption key + MEMCPY(tmp->step3b.hashseed, item->ovk, OVK_SET_SIZE); + cx_hash_sha256(tmp->step3b.hashseed, OVK_SET_SIZE, tmp->step3b.outkey, + CX_SHA256_SIZE); + // replace the first 0x00 of the copied ovk with 0x01, hash again, this + // will be the first half of the plaintext to encrypt + tmp->step3b.hashseed[0] = 0x01; + cx_hash_sha256(tmp->step3b.hashseed, OVK_SET_SIZE, + tmp->step3b.encciph_part1, CX_SHA256_SIZE); + // replace the first 0x01 of the copied ovk with 0x02, hash again, this + // will be the second half of the plaintext to encrypt + tmp->step3b.hashseed[0] = 0x02; + cx_hash_sha256(tmp->step3b.hashseed, OVK_SET_SIZE, + tmp->step3b.encciph_part2, CX_SHA256_SIZE); + MEMZERO(tmp->step3b.chachanonce, CHACHA_NONCE_SIZE); + // tmp->step4b.encciph = tmp->step3b.encciph_part1 || + // tmp->step3b.encciph_part2 encrypt and compare computed encryption to + // that provided in the transaction data + chacha(tmp->step4b.encciph, tmp->step4b.encciph, ENC_CIPHER_SIZE, + tmp->step4b.outkey, tmp->step4b.chachanonce, 1); + if (MEMCMP(tmp->step4b.encciph, + start_outputdata + INDEX_OUTPUT_OUT + i * OUTPUT_TX_LEN, + ENC_CIPHER_SIZE) != 0) { return zxerr_unknown; + } } - - return zxerr_ok; //or some code for ok -} - -typedef struct { - union { - // STEP 1 - struct { // MAX SIZE --> 160 - uint8_t dummy[MAX_SIZE - EPK_SIZE - ESK_SIZE]; - uint8_t epk[EPK_SIZE]; //computed from receiver diversifier - uint8_t esk[ESK_SIZE]; - } step1; - - struct{ - uint8_t chachanonce[CHACHA_NONCE_SIZE]; - uint8_t compactout[COMPACT_OUT_SIZE]; - uint8_t sharedkey[SHARED_KEY_SIZE]; - uint8_t epk[EPK_SIZE]; - uint8_t esk[ESK_SIZE]; - } step2; - - struct{ - uint8_t dummy[MAX_SIZE - OVK_SIZE - VALUE_COMMITMENT_SIZE - NOTE_COMMITMENT_SIZE - EPK_SIZE - ESK_SIZE]; - uint8_t ovk[OVK_SIZE]; - uint8_t valuecmt[VALUE_COMMITMENT_SIZE]; - uint8_t notecmt[NOTE_COMMITMENT_SIZE]; - uint8_t epk[EPK_SIZE]; - uint8_t esk[ESK_SIZE]; - }step3; - - struct{ - uint8_t dummy[MAX_SIZE - PRF_INPUT_SIZE - ESK_SIZE]; - uint8_t prfinput[PRF_INPUT_SIZE]; - uint8_t esk[ESK_SIZE]; - }step4; - - struct{ - uint8_t outkey[OUT_KEY_SIZE]; - uint8_t dummy[MAX_SIZE - OUT_KEY_SIZE - PKD_SIZE - ESK_SIZE]; - uint8_t pkd[PKD_SIZE]; - uint8_t esk[ESK_SIZE]; - }step5; - - struct{ - uint8_t outkey[OUT_KEY_SIZE]; - uint8_t dummy[MAX_SIZE - OUT_KEY_SIZE - ENC_CIPHER_SIZE - CHACHA_NONCE_SIZE]; - uint8_t chachanonce[CHACHA_NONCE_SIZE]; - uint8_t encciph[ENC_CIPHER_SIZE]; - }step6; - - struct{ - uint8_t hashseed[OVK_SET_SIZE]; - uint8_t outkey[OUT_KEY_SIZE]; - uint8_t encciph_part1[ENC_CIPHER_HALVE_SIZE]; - uint8_t encciph_part2[ENC_CIPHER_HALVE_SIZE]; - uint8_t chachanonce[CHACHA_NONCE_SIZE]; - }step3b; - struct{ - uint8_t hashseed[OVK_SET_SIZE]; - uint8_t outkey[OUT_KEY_SIZE]; - uint8_t encciph[ENC_CIPHER_SIZE]; - uint8_t chachanonce[CHACHA_NONCE_SIZE]; - }step4b; - }; -} tmp_enc; - -// handleCheckandSign step 8/11 -zxerr_t crypto_checkencryptions_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata) { - zemu_log_stack("crypto_checkencryptions_sapling"); + CHECK_APP_CANARY() MEMZERO(buffer, bufferLen); - tmp_enc *tmp = (tmp_enc *)buffer; - - const uint8_t *start_outputdata = (uint8_t *)(txdata + length_t_in_data() + length_spenddata()); - - //the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last part of hdPath - for(uint8_t i = 0; i < outputlist_len(); i++) { - // retrieve info on list of outputs stored in flash - const output_item_t *item = outputlist_retrieve_item(i); - if (item == NULL){ - return zxerr_unknown; - } - // compute random ephemeral private and public keys (esk,epk) from seed and diversifier - rseed_get_esk_epk(item->rseed,(uint8_t *) item->div, tmp->step1.esk, tmp->step1.epk); - CHECK_APP_CANARY() - - // compare the computed epk to that provided in the transaction data - if (MEMCMP(tmp->step1.epk, start_outputdata + INDEX_OUTPUT_EPK + i * OUTPUT_TX_LEN, EPK_SIZE) != 0){ - return zxerr_unknown; - } - - // get shared key (used as encryption key) from esk, epk and pkd - ka_to_key(tmp->step1.esk, (uint8_t *) item->pkd, tmp->step1.epk, tmp->step2.sharedkey); - CHECK_APP_CANARY() - // encode (div, value rseed and memotype) into step2.compactout ready to be encrypted - prepare_enccompact_input((uint8_t *) item->div, item->value, (uint8_t *) item->rseed, item->memotype, tmp->step2.compactout); - CHECK_APP_CANARY() - MEMZERO(tmp->step2.chachanonce,CHACHA_NONCE_SIZE); - // encrypt the previously obtained encoding, and store it in step2.compactoutput (reusing the same memory for input and output) - chacha(tmp->step2.compactout, tmp->step2.compactout, COMPACT_OUT_SIZE, tmp->step2.sharedkey, tmp->step2.chachanonce,1); - CHECK_APP_CANARY() - // check that the computed encryption is the same as that provided in the transaction data - if (MEMCMP(tmp->step2.compactout, start_outputdata + INDEX_OUTPUT_ENC + i * OUTPUT_TX_LEN, COMPACT_OUT_SIZE) != 0) { - return zxerr_unknown; - } - - // if an ovk was provided - if (item->ovk[0] != 0x00) { - // copy ovk, the value commitment and note-commitment from flash memory and transaction to - // local tmp structure so as to hash - MEMCPY(tmp->step3.ovk, item->ovk + 1, OVK_SIZE); - MEMCPY(tmp->step3.valuecmt, start_outputdata + INDEX_OUTPUT_VALUECMT + i* OUTPUT_TX_LEN,VALUE_COMMITMENT_SIZE); - MEMCPY(tmp->step3.notecmt, start_outputdata + INDEX_OUTPUT_NOTECMT + i* OUTPUT_TX_LEN,NOTE_COMMITMENT_SIZE); - // Note that tmp->step4.prfinput is the same memory chunk as the concatenation of - // tmp->step3.ovk || tmp->step3.valuecmt || tmp->step3.notecmt || tmp->step3.epk - // so next we hash that concatenation, and store hash in tmp->step5.outkey - blake2b_prf(tmp->step4.prfinput, tmp->step5.outkey); - CHECK_APP_CANARY() - - // get pkd from flash memory, store it in tmp->step5.pkd - MEMCPY(tmp->step5.pkd, item->pkd, PKD_SIZE); - - MEMZERO(tmp->step6.chachanonce,CHACHA_NONCE_SIZE); - - // tmp->step6.encciph = tmp->step5.pkd || tmp->step5.esk - // encrypt that, using as encryption key the output of the blake2b PRF - // store resulting ciphertext in tmp->step6.encciph - chacha(tmp->step6.encciph, tmp->step6.encciph, ENC_CIPHER_SIZE, tmp->step6.outkey, tmp->step6.chachanonce,1); - CHECK_APP_CANARY() - - // check that the computed encryption is the same as that provided in the transaction data - if (MEMCMP(tmp->step6.encciph, start_outputdata + INDEX_OUTPUT_OUT + i * OUTPUT_TX_LEN, ENC_CIPHER_SIZE) != 0) { - return zxerr_unknown; - } - - // if no ovk was provided - } else { - // copy the contents of flash memory for ovk, and hash it. This hash will be the encryption key - MEMCPY(tmp->step3b.hashseed, item->ovk, OVK_SET_SIZE); - cx_hash_sha256(tmp->step3b.hashseed, OVK_SET_SIZE, tmp->step3b.outkey, CX_SHA256_SIZE); - // replace the first 0x00 of the copied ovk with 0x01, hash again, this will be - // the first half of the plaintext to encrypt - tmp->step3b.hashseed[0] = 0x01; - cx_hash_sha256(tmp->step3b.hashseed, OVK_SET_SIZE, tmp->step3b.encciph_part1, CX_SHA256_SIZE); - // replace the first 0x01 of the copied ovk with 0x02, hash again, this will be - // the second half of the plaintext to encrypt - tmp->step3b.hashseed[0] = 0x02; - cx_hash_sha256(tmp->step3b.hashseed, OVK_SET_SIZE, tmp->step3b.encciph_part2, CX_SHA256_SIZE); - MEMZERO(tmp->step3b.chachanonce,CHACHA_NONCE_SIZE); - // tmp->step4b.encciph = tmp->step3b.encciph_part1 || tmp->step3b.encciph_part2 - // encrypt and compare computed encryption to that provided in the transaction data - chacha(tmp->step4b.encciph, tmp->step4b.encciph, ENC_CIPHER_SIZE, tmp->step4b.outkey, tmp->step4b.chachanonce,1); - if (MEMCMP(tmp->step4b.encciph, start_outputdata + INDEX_OUTPUT_OUT + i * OUTPUT_TX_LEN, ENC_CIPHER_SIZE) != 0){ - return zxerr_unknown; - } - } - CHECK_APP_CANARY() - MEMZERO(buffer, bufferLen); - } + } - MEMZERO(buffer, bufferLen); - return zxerr_ok; //or some code for ok + MEMZERO(buffer, bufferLen); + return zxerr_ok; // or some code for ok } -void address_to_script(uint8_t *address, uint8_t *output){ - uint8_t script[SCRIPT_SIZE] = {0}; - script[0] = 0x19; - script[1] = 0x76; - script[2] = 0xa9; - script[3] = 0x14; - - uint8_t tmp[HASH_SIZE] = {0}; - cx_hash_sha256(address, PK_LEN_SECP256K1, tmp, CX_SHA256_SIZE); - ripemd160(tmp, CX_SHA256_SIZE, script + SCRIPT_CONSTS_SIZE); - script[24] = 0x88; - script[25] = 0xac; - MEMCPY(output, script, SCRIPT_SIZE); +void address_to_script(uint8_t *address, uint8_t *output) { + uint8_t script[SCRIPT_SIZE] = {0}; + script[0] = 0x19; + script[1] = 0x76; + script[2] = 0xa9; + script[3] = 0x14; + + uint8_t tmp[HASH_SIZE] = {0}; + cx_hash_sha256(address, PK_LEN_SECP256K1, tmp, CX_SHA256_SIZE); + ripemd160(tmp, CX_SHA256_SIZE, script + SCRIPT_CONSTS_SIZE); + script[24] = 0x88; + script[25] = 0xac; + MEMCPY(output, script, SCRIPT_SIZE); } typedef struct { - union { - // STEP 1 - struct { - uint8_t r[SIG_R_SIZE]; - uint8_t s[SIG_S_SIZE]; - uint8_t v; - // DER signature max size should be 73 - // https://bitcoin.stackexchange.com/questions/77191/what-is-the-maximum-size-of-a-der-encoded-ecdsa-signature#77192 - uint8_t der_signature[DER_MAX_SIZE]; - } step1; - - struct { - uint8_t rs[SIG_R_SIZE + SIG_S_SIZE]; - uint8_t dummy[DER_MAX_SIZE + 1]; - } step2; - }; + union { + // STEP 1 + struct { + uint8_t r[SIG_R_SIZE]; + uint8_t s[SIG_S_SIZE]; + uint8_t v; + // DER signature max size should be 73 + // https://bitcoin.stackexchange.com/questions/77191/what-is-the-maximum-size-of-a-der-encoded-ecdsa-signature#77192 + uint8_t der_signature[DER_MAX_SIZE]; + } step1; + + struct { + uint8_t rs[SIG_R_SIZE + SIG_S_SIZE]; + uint8_t dummy[DER_MAX_SIZE + 1]; + } step2; + }; } __attribute__((packed)) signature_tr; // handleCheckandSign step 9/11 -zxerr_t crypto_sign_and_check_transparent(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen, const uint8_t tx_version) { - zemu_log_stack("crypto_sign_and_check_transparent"); - if(t_inlist_len() == 0){ - return zxerr_ok; - } - MEMZERO(buffer, bufferLen); - - // todo: not always SAPLING_LENGTH_HASH_DATA - if(length_t_in_data() + length_spenddata() + length_outputdata() + SAPLING_LENGTH_HASH_DATA != txdatalen){ - return zxerr_unknown; - } - - if(get_state() != STATE_VERIFIED_ALL_TXDATA ){ - return zxerr_unknown; - } - - uint8_t *start_tindata = (uint8_t *)txdata; - uint8_t *start_signdata = (uint8_t *)(txdata + start_sighashdata()); - - uint8_t *out = (uint8_t *) buffer; - MEMZERO(out, bufferLen); - - cx_ecfp_public_key_t cx_publicKey = {0}; - cx_ecfp_private_key_t cx_privateKey = {0}; - uint8_t privateKeyData[64] = {0}; - uint8_t pubKey[PUB_KEY_SIZE+1] = {0}; - uint8_t script[SCRIPT_SIZE] = {0}; - uint8_t message_digest[HASH_SIZE] = {0}; - - unsigned int info = 0; - signature_tr *const signature = (signature_tr *) buffer; - // Temporarily get sk from Ed25519 - zxerr_t error = zxerr_unknown; - CHECK_APP_CANARY() - const u_int8_t tInListLen = t_inlist_len(); - for (uint8_t i = 0; i < tInListLen; i++) { - const t_input_item_t *item = t_inlist_retrieve_item(i); - - CATCH_CXERROR(os_derive_bip32_no_throw(CX_CURVE_256K1, - item->path, - HDPATH_LEN_DEFAULT, - privateKeyData, NULL)) - CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_256K1, privateKeyData, SK_SECP256K1_SIZE, &cx_privateKey)) - CATCH_CXERROR(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, NULL, 0, &cx_publicKey)) - CATCH_CXERROR(cx_ecfp_generate_pair_no_throw(CX_CURVE_256K1, &cx_publicKey, &cx_privateKey, 1)) - - for (int j = 0; j < PUB_KEY_SIZE; j++) { - pubKey[j] = cx_publicKey.W[SIG_S_SIZE + SIG_R_SIZE - j]; - } - cx_publicKey.W[0] = cx_publicKey.W[SIG_S_SIZE + SIG_R_SIZE] & 1 ? 0x03 : 0x02; // "Compress" public key in place - if ((cx_publicKey.W[SIG_R_SIZE] & 1) != 0) { - pubKey[PUB_KEY_SIZE - 1] |= 0x80; - } - MEMCPY(pubKey, cx_publicKey.W, PK_LEN_SECP256K1); - address_to_script(pubKey,script); - if(MEMCMP(script,(uint8_t *)(start_tindata + INDEX_TIN_SCRIPT + i * T_IN_TX_LEN), SCRIPT_SIZE) != 0){ - goto catch_cx_error; - } - if(MEMCMP(item->script, script, SCRIPT_SIZE) != 0){ - goto catch_cx_error; - } - - uint64_t value = 0; - { - parser_context_t pars_ctx; - parser_error_t pars_err; - - pars_ctx.offset = 0; - pars_ctx.buffer = start_tindata + INDEX_TIN_VALUE + i * T_IN_TX_LEN; - pars_ctx.bufferLen = 8; - pars_err = _readUInt64(&pars_ctx, &value); - if (pars_err != parser_ok){ - goto catch_cx_error; - } - } - - if(value != item->value){ - goto catch_cx_error; - } - signature_script_hash(start_tindata, start_signdata, SAPLING_LENGTH_HASH_DATA, start_tindata + i * T_IN_TX_LEN, T_IN_TX_LEN, i, tx_version, message_digest); - size_t signatureLen = DER_MAX_SIZE; - CATCH_CXERROR(cx_ecdsa_sign_no_throw(&cx_privateKey, - CX_RND_RFC6979 | CX_LAST, - CX_SHA256, - message_digest, - CX_SHA256_SIZE, - signature->step1.der_signature, - &signatureLen, - &info)) - - if (convertDERtoRSV(signature->step1.der_signature, info, signature->step1.r, signature->step1.s, &signature->step1.v) != no_error || - transparent_signatures_append(signature->step2.rs) != zxerr_ok) { - goto catch_cx_error; - } - } - error = zxerr_ok; +zxerr_t crypto_sign_and_check_transparent(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint16_t txdatalen, + const uint8_t tx_version) { + zemu_log_stack("crypto_sign_and_check_transparent"); + if (t_inlist_len() == 0) { + return zxerr_ok; + } + MEMZERO(buffer, bufferLen); + + // todo: not always SAPLING_LENGTH_HASH_DATA + if (length_t_in_data() + length_spenddata() + length_outputdata() + + SAPLING_LENGTH_HASH_DATA != + txdatalen) { + return zxerr_unknown; + } + + if (get_state() != STATE_VERIFIED_ALL_TXDATA) { + return zxerr_unknown; + } + + uint8_t *start_tindata = (uint8_t *)txdata; + uint8_t *start_signdata = (uint8_t *)(txdata + start_sighashdata()); + + uint8_t *out = (uint8_t *)buffer; + MEMZERO(out, bufferLen); + + cx_ecfp_public_key_t cx_publicKey = {0}; + cx_ecfp_private_key_t cx_privateKey = {0}; + uint8_t privateKeyData[64] = {0}; + uint8_t pubKey[PUB_KEY_SIZE + 1] = {0}; + uint8_t script[SCRIPT_SIZE] = {0}; + uint8_t message_digest[HASH_SIZE] = {0}; + + unsigned int info = 0; + signature_tr *const signature = (signature_tr *)buffer; + // Temporarily get sk from Ed25519 + zxerr_t error = zxerr_unknown; + CHECK_APP_CANARY() + const u_int8_t tInListLen = t_inlist_len(); + for (uint8_t i = 0; i < tInListLen; i++) { + const t_input_item_t *item = t_inlist_retrieve_item(i); + + CATCH_CXERROR(os_derive_bip32_no_throw( + CX_CURVE_256K1, item->path, HDPATH_LEN_DEFAULT, privateKeyData, NULL)) + CATCH_CXERROR(cx_ecfp_init_private_key_no_throw( + CX_CURVE_256K1, privateKeyData, SK_SECP256K1_SIZE, &cx_privateKey)) + CATCH_CXERROR(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, NULL, 0, + &cx_publicKey)) + CATCH_CXERROR(cx_ecfp_generate_pair_no_throw(CX_CURVE_256K1, &cx_publicKey, + &cx_privateKey, 1)) + + for (int j = 0; j < PUB_KEY_SIZE; j++) { + pubKey[j] = cx_publicKey.W[SIG_S_SIZE + SIG_R_SIZE - j]; + } + cx_publicKey.W[0] = cx_publicKey.W[SIG_S_SIZE + SIG_R_SIZE] & 1 + ? 0x03 + : 0x02; // "Compress" public key in place + if ((cx_publicKey.W[SIG_R_SIZE] & 1) != 0) { + pubKey[PUB_KEY_SIZE - 1] |= 0x80; + } + MEMCPY(pubKey, cx_publicKey.W, PK_LEN_SECP256K1); + address_to_script(pubKey, script); + if (MEMCMP(script, + (uint8_t *)(start_tindata + INDEX_TIN_SCRIPT + i * T_IN_TX_LEN), + SCRIPT_SIZE) != 0) { + goto catch_cx_error; + } + if (MEMCMP(item->script, script, SCRIPT_SIZE) != 0) { + goto catch_cx_error; + } + + uint64_t value = 0; + { + parser_context_t pars_ctx; + parser_error_t pars_err; + + pars_ctx.offset = 0; + pars_ctx.buffer = start_tindata + INDEX_TIN_VALUE + i * T_IN_TX_LEN; + pars_ctx.bufferLen = 8; + pars_err = _readUInt64(&pars_ctx, &value); + if (pars_err != parser_ok) { + goto catch_cx_error; + } + } + + if (value != item->value) { + goto catch_cx_error; + } + signature_script_hash(start_tindata, start_signdata, + SAPLING_LENGTH_HASH_DATA, + start_tindata + i * T_IN_TX_LEN, T_IN_TX_LEN, i, + tx_version, message_digest); + size_t signatureLen = DER_MAX_SIZE; + CATCH_CXERROR(cx_ecdsa_sign_no_throw( + &cx_privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256, message_digest, + CX_SHA256_SIZE, signature->step1.der_signature, &signatureLen, &info)) + + if (convertDERtoRSV(signature->step1.der_signature, info, + signature->step1.r, signature->step1.s, + &signature->step1.v) != no_error || + transparent_signatures_append(signature->step2.rs) != zxerr_ok) { + goto catch_cx_error; + } + } + error = zxerr_ok; catch_cx_error: - MEMZERO(&cx_publicKey, sizeof(cx_publicKey)); - MEMZERO(&cx_privateKey, sizeof(cx_privateKey)); - MEMZERO(privateKeyData, sizeof(privateKeyData)); - MEMZERO(pubKey, sizeof(pubKey)); - MEMZERO(script, sizeof(script)); - MEMZERO(message_digest, sizeof(message_digest)); - - return error; + MEMZERO(&cx_publicKey, sizeof(cx_publicKey)); + MEMZERO(&cx_privateKey, sizeof(cx_privateKey)); + MEMZERO(privateKeyData, sizeof(privateKeyData)); + MEMZERO(pubKey, sizeof(pubKey)); + MEMZERO(script, sizeof(script)); + MEMZERO(message_digest, sizeof(message_digest)); + + return error; } - typedef struct { - union { - // STEP 1 - struct { - uint8_t zip32_seed[ZIP32_SEED_SIZE]; - } step1; - - struct { - uint8_t ask[ASK_SIZE]; - uint8_t nsk[NSK_SIZE]; - } step2; - // STEP 2 - struct { - uint8_t rsk[ASK_SIZE]; - } step3; - }; + union { + // STEP 1 + struct { + uint8_t zip32_seed[ZIP32_SEED_SIZE]; + } step1; + + struct { + uint8_t ask[ASK_SIZE]; + uint8_t nsk[NSK_SIZE]; + } step2; + // STEP 2 + struct { + uint8_t rsk[ASK_SIZE]; + } step3; + }; } tmp_sign_s; // handleCheckandSign step 10/11 -zxerr_t crypto_signspends_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen, const uint8_t tx_version) { - zemu_log_stack("crypto_signspends_sapling"); - if(spendlist_len() == 0){ - return zxerr_ok; - } - - MEMZERO(buffer, bufferLen); - - if(get_state() != STATE_VERIFIED_ALL_TXDATA ){ - return zxerr_unknown; - } - - if(length_t_in_data() + length_spenddata() + length_outputdata() + SAPLING_LENGTH_HASH_DATA != txdatalen){ - return zxerr_unknown; - } - - uint8_t *start_signdata = (uint8_t *)(txdata + start_sighashdata()); - uint8_t message[HASH_SIZE + 32] = {0}; - signature_hash(txdata, start_signdata,SAPLING_LENGTH_HASH_DATA, tx_version, message + 32); - tmp_sign_s tmp = {0}; - - //the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last part of hdPath - // Temporarily get sk from Ed25519 - const uint8_t spendListLen = spendlist_len(); - for (uint8_t i = 0; i < spendListLen; i++) { - CHECK_ZXERROR_AND_CLEAN(crypto_fillSaplingSeed(tmp.step1.zip32_seed)) - const spend_item_t *item = spendlist_retrieve_item(i); - if (item == NULL){ - CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) - } - // combining these causes a stack overflow - randomized_secret_from_seed(tmp.step1.zip32_seed,item->path, (uint8_t *)item->alpha, tmp.step3.rsk); - rsk_to_rk((uint8_t *)tmp.step3.rsk, message); - - sign_redjubjub(tmp.step3.rsk, message, buffer); - CHECK_ZXERROR_AND_CLEAN(spend_signatures_append(buffer)) - MEMZERO(&tmp, sizeof(tmp_sign_s)); - CHECK_APP_CANARY() +zxerr_t crypto_signspends_sapling(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint16_t txdatalen, + const uint8_t tx_version) { + zemu_log_stack("crypto_signspends_sapling"); + if (spendlist_len() == 0) { + return zxerr_ok; + } + + MEMZERO(buffer, bufferLen); + + if (get_state() != STATE_VERIFIED_ALL_TXDATA) { + return zxerr_unknown; + } + + if (length_t_in_data() + length_spenddata() + length_outputdata() + + SAPLING_LENGTH_HASH_DATA != + txdatalen) { + return zxerr_unknown; + } + + uint8_t *start_signdata = (uint8_t *)(txdata + start_sighashdata()); + uint8_t message[HASH_SIZE + 32] = {0}; + signature_hash(txdata, start_signdata, SAPLING_LENGTH_HASH_DATA, tx_version, + message + 32); + tmp_sign_s tmp = {0}; + + // the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last + // part of hdPath + // Temporarily get sk from Ed25519 + const uint8_t spendListLen = spendlist_len(); + for (uint8_t i = 0; i < spendListLen; i++) { + CHECK_ZXERROR_AND_CLEAN(crypto_fillSaplingSeed(tmp.step1.zip32_seed)) + const spend_item_t *item = spendlist_retrieve_item(i); + if (item == NULL) { + CHECK_ZXERROR_AND_CLEAN(zxerr_unknown) } + // combining these causes a stack overflow + randomized_secret_from_seed(tmp.step1.zip32_seed, item->path, + (uint8_t *)item->alpha, tmp.step3.rsk); + rsk_to_rk((uint8_t *)tmp.step3.rsk, message); + sign_redjubjub(tmp.step3.rsk, message, buffer); + CHECK_ZXERROR_AND_CLEAN(spend_signatures_append(buffer)) MEMZERO(&tmp, sizeof(tmp_sign_s)); - return zxerr_ok; + CHECK_APP_CANARY() + } + + MEMZERO(&tmp, sizeof(tmp_sign_s)); + return zxerr_ok; } // handleExtractTransparentSignature -zxerr_t crypto_extract_transparent_signature(uint8_t *buffer, uint16_t bufferLen){ - if(!transparent_signatures_more_extract()){ - return zxerr_unknown; - } - - if(get_state() != STATE_SIGNED_TX){ - return zxerr_unknown; - } - - MEMZERO(buffer, bufferLen); - return get_next_transparent_signature(buffer); +zxerr_t crypto_extract_transparent_signature(uint8_t *buffer, + uint16_t bufferLen) { + if (!transparent_signatures_more_extract()) { + return zxerr_unknown; + } + + if (get_state() != STATE_SIGNED_TX) { + return zxerr_unknown; + } + + MEMZERO(buffer, bufferLen); + return get_next_transparent_signature(buffer); } // handleExtractSpendSignature -zxerr_t crypto_extract_spend_signature(uint8_t *buffer, uint16_t bufferLen){ - if(!spend_signatures_more_extract()){ - return zxerr_unknown; - } +zxerr_t crypto_extract_spend_signature(uint8_t *buffer, uint16_t bufferLen) { + if (!spend_signatures_more_extract()) { + return zxerr_unknown; + } - if(get_state() != STATE_SIGNED_TX){ - return zxerr_unknown; - } + if (get_state() != STATE_SIGNED_TX) { + return zxerr_unknown; + } - MEMZERO(buffer, bufferLen); - return get_next_spend_signature(buffer); + MEMZERO(buffer, bufferLen); + return get_next_spend_signature(buffer); } // handleInitTX step 2/2 -- AND -- handleCheckandSign step 11/11 -zxerr_t crypto_hash_messagebuffer(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, uint16_t txdataLen){ - if(bufferLen < CX_SHA256_SIZE){ - return zxerr_unknown; - } - cx_hash_sha256(txdata, txdataLen, buffer, CX_SHA256_SIZE); // SHA256 - return zxerr_ok; +zxerr_t crypto_hash_messagebuffer(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, uint16_t txdataLen) { + if (bufferLen < CX_SHA256_SIZE) { + return zxerr_unknown; + } + cx_hash_sha256(txdata, txdataLen, buffer, CX_SHA256_SIZE); // SHA256 + return zxerr_ok; } typedef struct { - uint8_t ivk[IVK_SIZE]; - uint8_t default_div[DIV_SIZE]; + uint8_t ivk[IVK_SIZE]; + uint8_t default_div[DIV_SIZE]; } tmp_sapling_ivk_and_default_div; -// handleGetKeyIVK: return the incoming viewing key for a given path and the default diversifier -zxerr_t crypto_ivk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint16_t *replyLen) { - zemu_log_stack("crypto_ivk_sapling"); +// handleGetKeyIVK: return the incoming viewing key for a given path and the +// default diversifier +zxerr_t crypto_ivk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, + uint16_t *replyLen) { + zemu_log_stack("crypto_ivk_sapling"); - tmp_sapling_ivk_and_default_div *out = (tmp_sapling_ivk_and_default_div *) buffer; - MEMZERO(buffer, bufferLen); + tmp_sapling_ivk_and_default_div *out = + (tmp_sapling_ivk_and_default_div *)buffer; + MEMZERO(buffer, bufferLen); - //the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last part of hdPath - uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; - - // Temporarily get sk from Ed25519 - if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { - MEMZERO(buffer, bufferLen); - MEMZERO(zip32_seed, sizeof(zip32_seed)); - *replyLen = 0; - return zxerr_unknown; - } + // the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last + // part of hdPath + uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; - CHECK_APP_CANARY() - // get incomming viewing key - zip32_ivk(zip32_seed, out->ivk, p); - CHECK_APP_CANARY() - // get default diversifier for start index 0 - get_default_diversifier_without_start_index(zip32_seed, p, out->default_div); + // Temporarily get sk from Ed25519 + if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { + MEMZERO(buffer, bufferLen); MEMZERO(zip32_seed, sizeof(zip32_seed)); - CHECK_APP_CANARY() - *replyLen = IVK_SIZE + DIV_SIZE; - return zxerr_ok; + *replyLen = 0; + return zxerr_unknown; + } + + CHECK_APP_CANARY() + // get incomming viewing key + zip32_ivk(zip32_seed, out->ivk, p); + CHECK_APP_CANARY() + // get default diversifier for start index 0 + get_default_diversifier_without_start_index(zip32_seed, p, out->default_div); + MEMZERO(zip32_seed, sizeof(zip32_seed)); + CHECK_APP_CANARY() + *replyLen = IVK_SIZE + DIV_SIZE; + return zxerr_ok; } // handleGetKeyOVK -zxerr_t crypto_ovk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint16_t *replyLen){ - MEMZERO(buffer, bufferLen); - - zemu_log_stack("crypto_ovk_sapling"); - uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; - +zxerr_t crypto_ovk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, + uint16_t *replyLen) { + MEMZERO(buffer, bufferLen); - // Temporarily get sk from Ed25519 - if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { - MEMZERO(zip32_seed, sizeof(zip32_seed)); - MEMZERO(buffer, bufferLen); - *replyLen = 0; - return zxerr_unknown; - } - CHECK_APP_CANARY() + zemu_log_stack("crypto_ovk_sapling"); + uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; - zip32_ovk(zip32_seed, buffer, p); - CHECK_APP_CANARY() + // Temporarily get sk from Ed25519 + if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { MEMZERO(zip32_seed, sizeof(zip32_seed)); + MEMZERO(buffer, bufferLen); + *replyLen = 0; + return zxerr_unknown; + } + CHECK_APP_CANARY() - *replyLen = OVK_SIZE; - return zxerr_ok; + zip32_ovk(zip32_seed, buffer, p); + CHECK_APP_CANARY() + MEMZERO(zip32_seed, sizeof(zip32_seed)); + + *replyLen = OVK_SIZE; + return zxerr_ok; } typedef struct { - uint8_t fvk[AK_SIZE + NK_SIZE + OVK_SIZE]; + uint8_t fvk[AK_SIZE + NK_SIZE + OVK_SIZE]; } tmp_sapling_fvk; // handleGetKeyFVK: return the full viewing key for a given path -zxerr_t crypto_fvk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint16_t *replyLen) { +zxerr_t crypto_fvk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, + uint16_t *replyLen) { - zemu_log_stack("crypto_fvk_sapling"); + zemu_log_stack("crypto_fvk_sapling"); - MEMZERO(buffer, bufferLen); - tmp_sapling_fvk *out = (tmp_sapling_fvk *) buffer; - - //the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last part of hdPath - uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; - - // Temporarily get sk from Ed25519 - if (crypto_fillSaplingSeed(zip32_seed) !=zxerr_ok) { - MEMZERO(zip32_seed, sizeof(zip32_seed)); - MEMZERO(buffer, bufferLen); - *replyLen = 0; - return zxerr_unknown; - } - CHECK_APP_CANARY() + MEMZERO(buffer, bufferLen); + tmp_sapling_fvk *out = (tmp_sapling_fvk *)buffer; - // get full viewing key - zip32_fvk(zip32_seed, out->fvk, p); - CHECK_APP_CANARY() + // the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last + // part of hdPath + uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; + // Temporarily get sk from Ed25519 + if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { MEMZERO(zip32_seed, sizeof(zip32_seed)); - *replyLen = AK_SIZE + NK_SIZE + OVK_SIZE; - return zxerr_ok; + MEMZERO(buffer, bufferLen); + *replyLen = 0; + return zxerr_unknown; + } + CHECK_APP_CANARY() + + // get full viewing key + zip32_fvk(zip32_seed, out->fvk, p); + CHECK_APP_CANARY() + + MEMZERO(zip32_seed, sizeof(zip32_seed)); + *replyLen = AK_SIZE + NK_SIZE + OVK_SIZE; + return zxerr_ok; } // handleGetNullifier -zxerr_t crypto_nullifier_sapling(uint8_t *buffer, uint16_t bufferLen, uint64_t notepos, uint8_t *cm, - uint16_t *replyLen){ - zemu_log_stack("crypto_nullifier_sapling"); +zxerr_t crypto_nullifier_sapling(uint8_t *buffer, uint16_t bufferLen, + uint64_t notepos, uint8_t *cm, + uint16_t *replyLen) { + zemu_log_stack("crypto_nullifier_sapling"); - MEMZERO(buffer, bufferLen); + MEMZERO(buffer, bufferLen); - uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; - uint8_t nsk[NSK_SIZE] = {0}; - - if (crypto_fillSaplingSeed(zip32_seed) !=zxerr_ok) { - MEMZERO(zip32_seed, sizeof(zip32_seed)); - MEMZERO(buffer, bufferLen); - *replyLen = 0; - return zxerr_unknown; - } - CHECK_APP_CANARY() - // nk can be computed from nsk which itself can be computed from the seed. - zip32_nsk_from_seed(zip32_seed, nsk); - compute_nullifier(cm, notepos, nsk, buffer); - CHECK_APP_CANARY() + uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; + uint8_t nsk[NSK_SIZE] = {0}; + if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { MEMZERO(zip32_seed, sizeof(zip32_seed)); - MEMZERO(nsk, sizeof(nsk)); - *replyLen = NULLIFIER_SIZE; - return zxerr_ok; + MEMZERO(buffer, bufferLen); + *replyLen = 0; + return zxerr_unknown; + } + CHECK_APP_CANARY() + // nk can be computed from nsk which itself can be computed from the seed. + zip32_nsk_from_seed(zip32_seed, nsk); + compute_nullifier(cm, notepos, nsk, buffer); + CHECK_APP_CANARY() + + MEMZERO(zip32_seed, sizeof(zip32_seed)); + MEMZERO(nsk, sizeof(nsk)); + *replyLen = NULLIFIER_SIZE; + return zxerr_ok; } // handleGetDiversifierList -zxerr_t crypto_diversifier_with_startindex(uint8_t *buffer, uint32_t p, const uint8_t *startindex, uint16_t *replylen) { - zemu_log_stack("crypto_get_diversifiers_sapling"); +zxerr_t crypto_diversifier_with_startindex(uint8_t *buffer, uint32_t p, + const uint8_t *startindex, + uint16_t *replylen) { + zemu_log_stack("crypto_get_diversifiers_sapling"); - //the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last part of hdPath - uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; + // the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last + // part of hdPath + uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; - // Temporarily get sk from Ed25519 - if (crypto_fillSaplingSeed(zip32_seed) !=zxerr_ok) { - MEMZERO(zip32_seed, sizeof(zip32_seed)); - *replylen = 0; - return zxerr_unknown; - } - CHECK_APP_CANARY() + // Temporarily get sk from Ed25519 + if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { + MEMZERO(zip32_seed, sizeof(zip32_seed)); + *replylen = 0; + return zxerr_unknown; + } + CHECK_APP_CANARY() - get_diversifier_list_withstartindex(zip32_seed, p, startindex, buffer); - for(int i = 0; i < DIV_LIST_LENGTH; i++){ - if (!is_valid_diversifier(buffer + i * DIV_SIZE)){ - MEMZERO(buffer + i * DIV_SIZE, DIV_SIZE); - } + get_diversifier_list_withstartindex(zip32_seed, p, startindex, buffer); + for (int i = 0; i < DIV_LIST_LENGTH; i++) { + if (!is_valid_diversifier(buffer + i * DIV_SIZE)) { + MEMZERO(buffer + i * DIV_SIZE, DIV_SIZE); } + } - MEMZERO(zip32_seed, sizeof(zip32_seed)); - *replylen = DIV_LIST_LENGTH * DIV_SIZE; - return zxerr_ok; + MEMZERO(zip32_seed, sizeof(zip32_seed)); + *replylen = DIV_LIST_LENGTH * DIV_SIZE; + return zxerr_ok; } typedef struct { - union { - struct { - uint8_t diversifier[DIV_SIZE]; - uint8_t pkd[PKD_SIZE]; - }; - struct { - uint8_t address_raw[ADDR_LEN_SAPLING]; - char address_bech32[100]; - }; - struct { - uint8_t dummy[ADDR_LEN_SAPLING]; - uint8_t startindex[DIV_INDEX_SIZE]; - }; + union { + struct { + uint8_t diversifier[DIV_SIZE]; + uint8_t pkd[PKD_SIZE]; + }; + struct { + uint8_t address_raw[ADDR_LEN_SAPLING]; + char address_bech32[100]; + }; + struct { + uint8_t dummy[ADDR_LEN_SAPLING]; + uint8_t startindex[DIV_INDEX_SIZE]; }; + }; } tmp_buf_addr_s; // handleGetAddrSaplingDiv -zxerr_t crypto_fillAddress_with_diversifier_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint8_t *div, uint16_t *replyLen) { - if (bufferLen < sizeof(tmp_buf_addr_s)) { - return zxerr_unknown; - } +zxerr_t crypto_fillAddress_with_diversifier_sapling(uint8_t *buffer, + uint16_t bufferLen, + uint32_t p, uint8_t *div, + uint16_t *replyLen) { + if (bufferLen < sizeof(tmp_buf_addr_s)) { + return zxerr_unknown; + } - MEMZERO(buffer, bufferLen); + MEMZERO(buffer, bufferLen); - zemu_log_stack("crypto_fillAddress_with_div_sapling"); + zemu_log_stack("crypto_fillAddress_with_div_sapling"); - tmp_buf_addr_s *const out = (tmp_buf_addr_s *) buffer; + tmp_buf_addr_s *const out = (tmp_buf_addr_s *)buffer; - uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; + uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; - MEMCPY(out->diversifier, div, DIV_SIZE); - if (!is_valid_diversifier(out->diversifier)){ - return zxerr_unknown; - } - - // Temporarily get sk from Ed25519 - if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { - MEMZERO(zip32_seed, sizeof(zip32_seed)); - *replyLen = 0; - return zxerr_unknown; - } - CHECK_APP_CANARY() - - get_pkd(zip32_seed, p, out->diversifier, out->pkd); - CHECK_APP_CANARY() + MEMCPY(out->diversifier, div, DIV_SIZE); + if (!is_valid_diversifier(out->diversifier)) { + return zxerr_unknown; + } + // Temporarily get sk from Ed25519 + if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { MEMZERO(zip32_seed, sizeof(zip32_seed)); + *replyLen = 0; + return zxerr_unknown; + } + CHECK_APP_CANARY() - if (bech32EncodeFromBytes(out->address_bech32, sizeof_field(tmp_buf_addr_s, address_bech32), - BECH32_HRP, - out->address_raw, - sizeof_field(tmp_buf_addr_s, address_raw), - 1, BECH32_ENCODING_BECH32) != zxerr_ok) { + get_pkd(zip32_seed, p, out->diversifier, out->pkd); + CHECK_APP_CANARY() - MEMZERO(out, bufferLen); - *replyLen = 0; - return zxerr_unknown; - } + MEMZERO(zip32_seed, sizeof(zip32_seed)); - CHECK_APP_CANARY() - *replyLen = sizeof_field(tmp_buf_addr_s, address_raw) + strlen((const char *) out->address_bech32); - return zxerr_ok; + if (bech32EncodeFromBytes(out->address_bech32, + sizeof_field(tmp_buf_addr_s, address_bech32), + BECH32_HRP, out->address_raw, + sizeof_field(tmp_buf_addr_s, address_raw), 1, + BECH32_ENCODING_BECH32) != zxerr_ok) { + + MEMZERO(out, bufferLen); + *replyLen = 0; + return zxerr_unknown; + } + + CHECK_APP_CANARY() + *replyLen = sizeof_field(tmp_buf_addr_s, address_raw) + + strlen((const char *)out->address_bech32); + return zxerr_ok; } // handleGetAddrSapling -zxerr_t crypto_fillAddress_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint16_t *replyLen) { - if (bufferLen < sizeof(tmp_buf_addr_s)) { - return zxerr_unknown; - } - - zemu_log_stack("crypto_fillAddress_sapling"); - tmp_buf_addr_s *const out = (tmp_buf_addr_s *) buffer; - MEMZERO(buffer, bufferLen); - - //the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last part of hdPath - uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; - - // Temporarily get sk from Ed25519 - if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { - MEMZERO(zip32_seed, sizeof(zip32_seed)); - *replyLen = 0; - return zxerr_unknown; - } - CHECK_APP_CANARY() - - get_pkd_from_seed(zip32_seed, p, out->startindex, out->diversifier, out->pkd); - MEMZERO(out + DIV_SIZE, MAX_SIZE_BUF_ADDR - DIV_SIZE); - CHECK_APP_CANARY() - +zxerr_t crypto_fillAddress_sapling(uint8_t *buffer, uint16_t bufferLen, + uint32_t p, uint16_t *replyLen) { + if (bufferLen < sizeof(tmp_buf_addr_s)) { + return zxerr_unknown; + } + + zemu_log_stack("crypto_fillAddress_sapling"); + tmp_buf_addr_s *const out = (tmp_buf_addr_s *)buffer; + MEMZERO(buffer, bufferLen); + + // the path in zip32 is [FIRST_VALUE, COIN_TYPE, p] where p is u32 and last + // part of hdPath + uint8_t zip32_seed[ZIP32_SEED_SIZE] = {0}; + + // Temporarily get sk from Ed25519 + if (crypto_fillSaplingSeed(zip32_seed) != zxerr_ok) { MEMZERO(zip32_seed, sizeof(zip32_seed)); - if (bech32EncodeFromBytes(out->address_bech32, sizeof_field(tmp_buf_addr_s, address_bech32), - BECH32_HRP, - out->address_raw, - sizeof_field(tmp_buf_addr_s, address_raw), - 1, BECH32_ENCODING_BECH32) != zxerr_ok) { - MEMZERO(out, bufferLen); - *replyLen = 0; - return zxerr_unknown; - } - CHECK_APP_CANARY() - - *replyLen = sizeof_field(tmp_buf_addr_s, address_raw) + strlen((const char *) out->address_bech32); - return zxerr_ok; + *replyLen = 0; + return zxerr_unknown; + } + CHECK_APP_CANARY() + + get_pkd_from_seed(zip32_seed, p, out->startindex, out->diversifier, out->pkd); + MEMZERO(out + DIV_SIZE, MAX_SIZE_BUF_ADDR - DIV_SIZE); + CHECK_APP_CANARY() + + MEMZERO(zip32_seed, sizeof(zip32_seed)); + if (bech32EncodeFromBytes(out->address_bech32, + sizeof_field(tmp_buf_addr_s, address_bech32), + BECH32_HRP, out->address_raw, + sizeof_field(tmp_buf_addr_s, address_raw), 1, + BECH32_ENCODING_BECH32) != zxerr_ok) { + MEMZERO(out, bufferLen); + *replyLen = 0; + return zxerr_unknown; + } + CHECK_APP_CANARY() + + *replyLen = sizeof_field(tmp_buf_addr_s, address_raw) + + strlen((const char *)out->address_bech32); + return zxerr_ok; } diff --git a/app/src/crypto.h b/app/src/crypto.h index 71b19e2d..e81bfe28 100644 --- a/app/src/crypto.h +++ b/app/src/crypto.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -20,12 +20,11 @@ extern "C" { #endif -#include #include "coin.h" -#include -#include #include "zxerror.h" - +#include +#include +#include extern uint32_t hdPath[HDPATH_LEN_DEFAULT]; @@ -33,55 +32,88 @@ extern address_kind_e addressKind; zxerr_t crypto_fillSaplingSeed(uint8_t *sk); -zxerr_t crypto_fillAddress_secp256k1(uint8_t *buffer, uint16_t bufferLen, uint16_t *replyLen); +zxerr_t crypto_fillAddress_secp256k1(uint8_t *buffer, uint16_t bufferLen, + uint16_t *replyLen); -zxerr_t crypto_fillAddress_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint16_t *replyLen); -zxerr_t crypto_fillAddress_with_diversifier_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint8_t *div, +zxerr_t crypto_fillAddress_sapling(uint8_t *buffer, uint16_t bufferLen, + uint32_t p, uint16_t *replyLen); +zxerr_t crypto_fillAddress_with_diversifier_sapling(uint8_t *buffer, + uint16_t bufferLen, + uint32_t p, uint8_t *div, uint16_t *replyLen); -zxerr_t crypto_diversifier_with_startindex(uint8_t *buffer, uint32_t p, const uint8_t *startindex, +zxerr_t crypto_diversifier_with_startindex(uint8_t *buffer, uint32_t p, + const uint8_t *startindex, uint16_t *replylen); -zxerr_t crypto_ivk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint16_t *replyLen); -zxerr_t crypto_ovk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint16_t *replyLen); -zxerr_t crypto_fvk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, uint16_t *replyLen); -zxerr_t crypto_nullifier_sapling(uint8_t *buffer, uint16_t bufferLen, uint64_t notepos, - uint8_t *cm, uint16_t *replyLen); - -zxerr_t crypto_hash_messagebuffer(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, uint16_t txdataLen); +zxerr_t crypto_ivk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, + uint16_t *replyLen); +zxerr_t crypto_ovk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, + uint16_t *replyLen); +zxerr_t crypto_fvk_sapling(uint8_t *buffer, uint16_t bufferLen, uint32_t p, + uint16_t *replyLen); +zxerr_t crypto_nullifier_sapling(uint8_t *buffer, uint16_t bufferLen, + uint64_t notepos, uint8_t *cm, + uint16_t *replyLen); -zxerr_t crypto_checkspend_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *spenddata, uint16_t spenddatalen, const uint8_t tx_version); +zxerr_t crypto_hash_messagebuffer(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, uint16_t txdataLen); -zxerr_t crypto_checkoutput_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *outputdata, - const uint16_t outputdatalen, const uint8_t tx_version); +zxerr_t crypto_checkspend_sapling(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *spenddata, + uint16_t spenddatalen, + const uint8_t tx_version); -zxerr_t crypto_checkencryptions_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *outputdata); +zxerr_t crypto_checkoutput_sapling(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *outputdata, + const uint16_t outputdatalen, + const uint8_t tx_version); -uint16_t crypto_key_exchange(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen); -zxerr_t crypto_extracttx_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen); +zxerr_t crypto_checkencryptions_sapling(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *outputdata); -zxerr_t crypto_extract_spend_proofkeyandrnd(uint8_t *buffer, uint16_t bufferLen); +uint16_t crypto_key_exchange(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, const uint16_t txdatalen); +zxerr_t crypto_extracttx_sapling(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint16_t txdatalen); -zxerr_t crypto_extract_output_rnd(uint8_t *buffer, uint16_t bufferLen, uint16_t *replyLen); +zxerr_t crypto_extract_spend_proofkeyandrnd(uint8_t *buffer, + uint16_t bufferLen); -zxerr_t crypto_signspends_sapling(uint8_t *buffer, uint16_t bufferLen, const uint8_t *signdata, uint16_t signdatalen, const uint8_t tx_version); +zxerr_t crypto_extract_output_rnd(uint8_t *buffer, uint16_t bufferLen, + uint16_t *replyLen); +zxerr_t crypto_signspends_sapling(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *signdata, uint16_t signdatalen, + const uint8_t tx_version); zxerr_t crypto_extract_spend_signature(uint8_t *buffer, uint16_t bufferLen); -zxerr_t crypto_check_prevouts(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint8_t tx_version); +zxerr_t crypto_check_prevouts(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, const uint8_t tx_version); -zxerr_t crypto_check_sequence(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint8_t tx_version); +zxerr_t crypto_check_sequence(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, const uint8_t tx_version); -zxerr_t crypto_check_outputs(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen, const uint8_t tx_version); +zxerr_t crypto_check_outputs(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, const uint16_t txdatalen, + const uint8_t tx_version); -zxerr_t crypto_check_joinsplits(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint8_t tx_version); +zxerr_t crypto_check_joinsplits(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint8_t tx_version); -zxerr_t crypto_check_valuebalance(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint8_t tx_version); +zxerr_t crypto_check_valuebalance(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint8_t tx_version); void address_to_script(uint8_t *address, uint8_t *output); -zxerr_t -crypto_sign_and_check_transparent(uint8_t *buffer, uint16_t bufferLen, const uint8_t *txdata, const uint16_t txdatalen, const uint8_t tx_version); -zxerr_t crypto_extract_transparent_signature(uint8_t *buffer, uint16_t bufferLen); +zxerr_t crypto_sign_and_check_transparent(uint8_t *buffer, uint16_t bufferLen, + const uint8_t *txdata, + const uint16_t txdatalen, + const uint8_t tx_version); +zxerr_t crypto_extract_transparent_signature(uint8_t *buffer, + uint16_t bufferLen); #ifdef __cplusplus } #endif diff --git a/app/src/index_NU5.h b/app/src/index_NU5.h index 14af7876..c770cfbd 100644 --- a/app/src/index_NU5.h +++ b/app/src/index_NU5.h @@ -1,36 +1,35 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include -#define NU5_LENGTH_HASH_DATA 220 +#define NU5_LENGTH_HASH_DATA 220 -#define NU5_INDEX_HASH_VERSION 0 -#define NU5_INDEX_HASH_VERSION_GROUP_ID 4 -#define NU5_INDEX_HASH_CONSENSUS_BRANCH_ID 8 -#define NU5_INDEX_HASH_LOCK_TIME 12 -#define NU5_INDEX_EXPIRY_HEIGHT 16 +#define NU5_INDEX_HASH_VERSION 0 +#define NU5_INDEX_HASH_VERSION_GROUP_ID 4 +#define NU5_INDEX_HASH_CONSENSUS_BRANCH_ID 8 +#define NU5_INDEX_HASH_LOCK_TIME 12 +#define NU5_INDEX_EXPIRY_HEIGHT 16 -#define NU5_INDEX_HASH_PREVOUTSHASH 20 // 32 bytes -#define NU5_INDEX_HASH_SEQUENCEHASH 52 // 32 bytes -#define NU5_INDEX_HASH_OUTPUTSHASH 84 // 32 bytes -#define NU5_INDEX_HASH_SHIELDEDSPENDHASH 116 // 32 bytes -#define NU5_INDEX_HASH_SHIELDEDOUTPUTHASH 148 // 32 bytes -#define NU5_INDEX_HASH_VALUEBALANCE 180 // 64 bit -#define NU5_INDEX_HASH_ORCHARDHASH 188 // of length 32 +#define NU5_INDEX_HASH_PREVOUTSHASH 20 // 32 bytes +#define NU5_INDEX_HASH_SEQUENCEHASH 52 // 32 bytes +#define NU5_INDEX_HASH_OUTPUTSHASH 84 // 32 bytes +#define NU5_INDEX_HASH_SHIELDEDSPENDHASH 116 // 32 bytes +#define NU5_INDEX_HASH_SHIELDEDOUTPUTHASH 148 // 32 bytes +#define NU5_INDEX_HASH_VALUEBALANCE 180 // 64 bit +#define NU5_INDEX_HASH_ORCHARDHASH 188 // of length 32 - -#define NU5_VALUEBALANCE_SIZE 8 // 64 bit +#define NU5_VALUEBALANCE_SIZE 8 // 64 bit diff --git a/app/src/index_sapling.c b/app/src/index_sapling.c index c869fd15..415260fb 100644 --- a/app/src/index_sapling.c +++ b/app/src/index_sapling.c @@ -1,42 +1,34 @@ /******************************************************************************* -* (c) 2020 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2020 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include "index_sapling.h" #include "nvdata.h" -uint16_t length_t_in_data() { - return t_inlist_len() * T_IN_TX_LEN; -}; +uint16_t length_t_in_data() { return t_inlist_len() * T_IN_TX_LEN; }; -uint16_t length_spend_old_data() { - return spendlist_len() * SPEND_OLD_TX_LEN; -} +uint16_t length_spend_old_data() { return spendlist_len() * SPEND_OLD_TX_LEN; } uint16_t length_spenddata() { - return spendlist_len() * (SPEND_TX_LEN + SPEND_OLD_TX_LEN); + return spendlist_len() * (SPEND_TX_LEN + SPEND_OLD_TX_LEN); }; -uint16_t length_outputdata() { - return outputlist_len() * OUTPUT_TX_LEN; -}; +uint16_t length_outputdata() { return outputlist_len() * OUTPUT_TX_LEN; }; -uint16_t length_spend_new_data() { - return spendlist_len() * SPEND_TX_LEN; -}; +uint16_t length_spend_new_data() { return spendlist_len() * SPEND_TX_LEN; }; uint16_t start_sighashdata() { - return length_t_in_data() + length_spenddata() + length_outputdata(); + return length_t_in_data() + length_spenddata() + length_outputdata(); }; diff --git a/app/src/index_sapling.h b/app/src/index_sapling.h index 4acfa02a..0f53f1c4 100644 --- a/app/src/index_sapling.h +++ b/app/src/index_sapling.h @@ -1,81 +1,84 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include -#define T_IN_INPUT_LEN 54 //fixme: maybe add more options to HDPATH -#define T_OUT_INPUT_LEN 34 -#define SPEND_INPUT_LEN 55 -#define OUTPUT_INPUT_LEN 85 - -#define INDEX_INPUT_TIN_PATH 0 -#define INDEX_INPUT_TIN_SCRIPT 20 -#define INDEX_INPUT_TIN_VALUE 46 - -#define INDEX_INPUT_TOUT_ADDR 0 -#define INDEX_INPUT_TOUT_VALUE 26 - -#define INDEX_INPUT_SPENDPOS 0 -#define INDEX_INPUT_INPUTDIV 4 -#define INDEX_INPUT_INPUTPKD 15 -#define INDEX_INPUT_INPUTVALUE 47 - -#define INDEX_INPUT_OUTPUTDIV 0 -#define INDEX_INPUT_OUTPUTPKD 11 -#define INDEX_INPUT_OUTPUTVALUE 43 -#define INDEX_INPUT_OUTPUTMEMO 51 -#define INDEX_INPUT_OUTPUTOVK 52 - -#define SPEND_EXTRACT_LEN 128 -#define OUTPUT_EXTRACT_LEN 64 - -#define T_IN_TX_LEN 74 // size of tx_in encoded as in bitcoin. The same across all tx versions -#define SPEND_OLD_TX_LEN 40 -#define SPEND_TX_LEN 320 // cv (32) + anchor (32) + nullifier (32) + rk (32) + zkproof (192) -#define OUTPUT_TX_LEN 948 - -#define INDEX_TIN_PREVOUT 0 -#define INDEX_TIN_SCRIPT 36 -#define INDEX_TIN_VALUE 62 -#define INDEX_TIN_SEQ 70 - -#define INDEX_SPEND_OLD_RCM 0 -#define INDEX_SPEND_OLD_NOTEPOS 32 - -#define INDEX_SPEND_VALUECMT 0 -#define INDEX_SPEND_ANCHOR 32 -#define INDEX_SPEND_NF 64 -#define INDEX_SPEND_RK 96 - -#define INDEX_OUTPUT_VALUECMT 0 -#define INDEX_OUTPUT_NOTECMT 32 -#define INDEX_OUTPUT_EPK 64 -#define INDEX_OUTPUT_ENC 96 -#define INDEX_OUTPUT_ENC_MEMO 96 + 52 // contents of the encrypted memo field -#define INDEX_OUTPUT_ENC_AEAD_TAG 96 + 564 // contents of the encrypted memo field -#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 T_IN_INPUT_LEN 54 // fixme: maybe add more options to HDPATH +#define T_OUT_INPUT_LEN 34 +#define SPEND_INPUT_LEN 55 +#define OUTPUT_INPUT_LEN 85 + +#define INDEX_INPUT_TIN_PATH 0 +#define INDEX_INPUT_TIN_SCRIPT 20 +#define INDEX_INPUT_TIN_VALUE 46 + +#define INDEX_INPUT_TOUT_ADDR 0 +#define INDEX_INPUT_TOUT_VALUE 26 + +#define INDEX_INPUT_SPENDPOS 0 +#define INDEX_INPUT_INPUTDIV 4 +#define INDEX_INPUT_INPUTPKD 15 +#define INDEX_INPUT_INPUTVALUE 47 + +#define INDEX_INPUT_OUTPUTDIV 0 +#define INDEX_INPUT_OUTPUTPKD 11 +#define INDEX_INPUT_OUTPUTVALUE 43 +#define INDEX_INPUT_OUTPUTMEMO 51 +#define INDEX_INPUT_OUTPUTOVK 52 + +#define SPEND_EXTRACT_LEN 128 +#define OUTPUT_EXTRACT_LEN 64 + +#define T_IN_TX_LEN \ + 74 // size of tx_in encoded as in bitcoin. The same across all tx versions +#define SPEND_OLD_TX_LEN 40 +#define SPEND_TX_LEN \ + 320 // cv (32) + anchor (32) + nullifier (32) + rk (32) + zkproof (192) +#define OUTPUT_TX_LEN 948 + +#define INDEX_TIN_PREVOUT 0 +#define INDEX_TIN_SCRIPT 36 +#define INDEX_TIN_VALUE 62 +#define INDEX_TIN_SEQ 70 + +#define INDEX_SPEND_OLD_RCM 0 +#define INDEX_SPEND_OLD_NOTEPOS 32 + +#define INDEX_SPEND_VALUECMT 0 +#define INDEX_SPEND_ANCHOR 32 +#define INDEX_SPEND_NF 64 +#define INDEX_SPEND_RK 96 + +#define INDEX_OUTPUT_VALUECMT 0 +#define INDEX_OUTPUT_NOTECMT 32 +#define INDEX_OUTPUT_EPK 64 +#define INDEX_OUTPUT_ENC 96 +#define INDEX_OUTPUT_ENC_MEMO 96 + 52 // contents of the encrypted memo field +#define INDEX_OUTPUT_ENC_AEAD_TAG \ + 96 + 564 // contents of the encrypted memo field +#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 uint16_t length_t_in_data(); diff --git a/app/src/jubjub.c b/app/src/jubjub.c index c0275162..40ff1aa0 100644 --- a/app/src/jubjub.c +++ b/app/src/jubjub.c @@ -1,384 +1,384 @@ /******************************************************************************* -* (c) 2021 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2021 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ -#include -#include #include "jubjub.h" #include "cx.h" +#include +#include +unsigned char const JUBJUB_FR_MODULUS_BYTES[JUBJUB_SCALAR_BYTES] = { + 14, 125, 180, 234, 101, 51, 175, 169, 6, 103, 59, + 1, 1, 52, 59, 0, 166, 104, 32, 147, 204, 200, + 16, 130, 208, 151, 14, 94, 214, 247, 44, 183}; -unsigned char const JUBJUB_FR_MODULUS_BYTES[JUBJUB_SCALAR_BYTES] = {14, 125, 180, 234, 101, 51, 175, 169, 6, 103, 59, 1, - 1, 52, 59, 0, 166, 104, 32, 147, 204, 200, 16, 130, - 208, 151, 14, 94, 214, 247, 44, 183}; - -unsigned char const JUBJUB_FQ_MODULUS_BYTES[JUBJUB_FIELD_BYTES] = {0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, - 0x39, 0xd8, 0x08, 0x09, 0xa1, 0xd8, 0x05, 0x53, 0xbd, - 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x01}; +unsigned char const JUBJUB_FQ_MODULUS_BYTES[JUBJUB_FIELD_BYTES] = { + 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, + 0x08, 0x09, 0xa1, 0xd8, 0x05, 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, + 0x5b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01}; -const jubjub_fq JUBJUB_FQ_ZERO = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +const jubjub_fq JUBJUB_FQ_ZERO = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -const jubjub_fq JUBJUB_FQ_ONE = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; +const jubjub_fq JUBJUB_FQ_ONE = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; -const jubjub_fq JUBJUB_FQ_EDWARDS_D = { - 42, 147, 24, 231, 75, 250, 43, 72, 245, 253, 146, 7, 230, 189, 127, 212, 41, 45, 127, 109, 55, 87, 157, 38, 1, - 6, 95, 214, 214, 52, 62, 177 -}; +const jubjub_fq JUBJUB_FQ_EDWARDS_D = {42, 147, 24, 231, 75, 250, 43, 72, + 245, 253, 146, 7, 230, 189, 127, 212, + 41, 45, 127, 109, 55, 87, 157, 38, + 1, 6, 95, 214, 214, 52, 62, 177}; -const jubjub_fq JUBJUB_FQ_EDWARDS_2D = {85, 38, 49, 206, 151, 244, 86, 145, 235, 251, 36, 15, 205, - 122, 255, 168, 82, 90, 254, 218, 110, 175, 58, 76, 2, 12, - 191, 173, 172, 104, 125, 98}; +const jubjub_fq JUBJUB_FQ_EDWARDS_2D = { + 85, 38, 49, 206, 151, 244, 86, 145, 235, 251, 36, 15, 205, 122, 255, 168, + 82, 90, 254, 218, 110, 175, 58, 76, 2, 12, 191, 173, 172, 104, 125, 98}; const jubjub_fq JUBJUB_FQ_SQRT_T = { - 0, 0, 0, 0, 57, 246, 211, 169, 148, 206, 190, 164, 25, 156, 236, 4, 4, 208, 236, 2, 169, 222, 210, 1, 127, 255, - 45, 255, 127, 255, 255, 255 -}; + 0, 0, 0, 0, 57, 246, 211, 169, 148, 206, 190, 164, 25, 156, 236, 4, + 4, 208, 236, 2, 169, 222, 210, 1, 127, 255, 45, 255, 127, 255, 255, 255}; const jubjub_fq JUBJUB_FQ_ROOT_OF_UNITY = { - 22, 162, 161, 158, 223, 232, 31, 32, 208, 155, 104, 25, 34, 200, 19, 180, 182, 54, 131, 80, 140, 34, 128, 185, - 56, 41, 151, 31, 67, 159, 13, 43 -}; + 22, 162, 161, 158, 223, 232, 31, 32, 208, 155, 104, 25, 34, 200, 19, 180, + 182, 54, 131, 80, 140, 34, 128, 185, 56, 41, 151, 31, 67, 159, 13, 43}; const jubjub_extendedpoint JUBJUB_GEN = { - .U = {9, 38, 212, 243, 32, 89, 199, 18, 212, 24, 167, 255, 38, 117, 59, 106, 213, 185, 167, 211, 239, 142, 40, - 39, 71, 191, 70, 146, 10, 149, 167, 83}, - .V = {87, 161, 1, 158, 109, 233, 182, 117, 83, 187, 55, 208, 194, 28, 253, 5, 109, 101, 103, 77, 206, 219, 221, - 188, 48, 86, 50, 173, 170, 242, 181, 48}, - .Z = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - .T1 = {9, 38, 212, 243, 32, 89, 199, 18, 212, 24, 167, 255, 38, 117, 59, 106, 213, 185, 167, 211, 239, 142, 40, - 39, 71, 191, 70, 146, 10, 149, 167, 83}, - .T2 = {87, 161, 1, 158, 109, 233, 182, 117, 83, 187, 55, 208, 194, 28, 253, 5, 109, 101, 103, 77, 206, 219, 221, - 188, 48, 86, 50, 173, 170, 242, 181, 48}, + .U = {9, 38, 212, 243, 32, 89, 199, 18, 212, 24, 167, + 255, 38, 117, 59, 106, 213, 185, 167, 211, 239, 142, + 40, 39, 71, 191, 70, 146, 10, 149, 167, 83}, + .V = {87, 161, 1, 158, 109, 233, 182, 117, 83, 187, 55, + 208, 194, 28, 253, 5, 109, 101, 103, 77, 206, 219, + 221, 188, 48, 86, 50, 173, 170, 242, 181, 48}, + .Z = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .T1 = {9, 38, 212, 243, 32, 89, 199, 18, 212, 24, 167, + 255, 38, 117, 59, 106, 213, 185, 167, 211, 239, 142, + 40, 39, 71, 191, 70, 146, 10, 149, 167, 83}, + .T2 = {87, 161, 1, 158, 109, 233, 182, 117, 83, 187, 55, + 208, 194, 28, 253, 5, 109, 101, 103, 77, 206, 219, + 221, 188, 48, 86, 50, 173, 170, 242, 181, 48}, }; const jubjub_extendedpoint JUBJUB_ID = { - .U = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - .V = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - .Z = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - .T1 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - .T2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .U = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .V = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .Z = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .T1 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .T2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, }; void u8_cmov(uint8_t *r, uint8_t a, uint8_t bit) { - uint8_t b = bit & 0x01; - uint8_t mask = (uint8_t)(-(int8_t) b); - uint8_t h, x; - h = *r; - x = h ^ a; - x &= mask; - *r = *r ^ x; + uint8_t b = bit & 0x01; + uint8_t mask = (uint8_t)(-(int8_t)b); + uint8_t h, x; + h = *r; + x = h ^ a; + x &= mask; + *r = *r ^ x; } void jubjub_field_frombytes(jubjub_fq r, const uint8_t *s) { - MEMZERO(r, sizeof(jubjub_fq)); - MEMCPY(r, s, sizeof(jubjub_fq)); - cx_math_modm_no_throw(r, JUBJUB_FIELD_BYTES, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); + MEMZERO(r, sizeof(jubjub_fq)); + MEMCPY(r, s, sizeof(jubjub_fq)); + cx_math_modm_no_throw(r, JUBJUB_FIELD_BYTES, JUBJUB_FQ_MODULUS_BYTES, + JUBJUB_FIELD_BYTES); } int jubjub_field_iszero(const jubjub_fq r) { - return cx_math_is_zero(r, JUBJUB_FIELD_BYTES); + return cx_math_is_zero(r, JUBJUB_FIELD_BYTES); } uint8_t jubjub_field_is_equal(const jubjub_fq a, const jubjub_fq b) { - return (MEMCMP(a, b, sizeof(jubjub_fq)) == 0) & 0x01; + return (MEMCMP(a, b, sizeof(jubjub_fq)) == 0) & 0x01; } void jubjub_field_one(jubjub_fq r) { - MEMZERO(r, sizeof(jubjub_fq)); - MEMCPY(r, JUBJUB_FQ_ONE, sizeof(jubjub_fq)); + MEMZERO(r, sizeof(jubjub_fq)); + MEMCPY(r, JUBJUB_FQ_ONE, sizeof(jubjub_fq)); } void jubjub_field_copy(jubjub_fq r, const jubjub_fq a) { - MEMZERO(r, sizeof(jubjub_fq)); - MEMCPY(r, a, sizeof(jubjub_fq)); + MEMZERO(r, sizeof(jubjub_fq)); + MEMCPY(r, a, sizeof(jubjub_fq)); } void jubjub_field_mult(jubjub_fq r, const jubjub_fq a, const jubjub_fq b) { - cx_math_multm_no_throw(r, a, b, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); + cx_math_multm_no_throw(r, a, b, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); } void jubjub_field_add(jubjub_fq r, const jubjub_fq a, const jubjub_fq b) { - cx_math_addm_no_throw(r, a, b, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); + cx_math_addm_no_throw(r, a, b, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); } void jubjub_field_sub(jubjub_fq r, const jubjub_fq a, const jubjub_fq b) { - cx_math_subm_no_throw(r, a, b, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); + cx_math_subm_no_throw(r, a, b, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); } void jubjub_field_inverse(jubjub_fq r, jubjub_fq a) { - cx_math_invprimem_no_throw(r, a, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); + cx_math_invprimem_no_throw(r, a, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); } void jubjub_field_square(jubjub_fq r, jubjub_fq a) { - cx_math_multm_no_throw(r, a, a, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); + cx_math_multm_no_throw(r, a, a, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); } void jubjub_field_double(jubjub_fq r, jubjub_fq a) { - cx_math_addm_no_throw(r, a, a, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); + cx_math_addm_no_throw(r, a, a, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); } void jubjub_field_pow_t(jubjub_fq r, const jubjub_fq a) { - cx_math_powm_no_throw(r, a, JUBJUB_FQ_SQRT_T, JUBJUB_FIELD_BYTES, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); + cx_math_powm_no_throw(r, a, JUBJUB_FQ_SQRT_T, JUBJUB_FIELD_BYTES, + JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); } void jubjub_field_negate(jubjub_fq r, const jubjub_fq a) { - cx_math_subm_no_throw(r, JUBJUB_FQ_ZERO, a, JUBJUB_FQ_MODULUS_BYTES, JUBJUB_FIELD_BYTES); + cx_math_subm_no_throw(r, JUBJUB_FQ_ZERO, a, JUBJUB_FQ_MODULUS_BYTES, + JUBJUB_FIELD_BYTES); } void jubjub_field_cmov(jubjub_fq r, const jubjub_fq a, uint8_t bit) { - uint8_t b = bit & 0x01; - uint8_t mask = (uint8_t)(-(int8_t) b); - jubjub_fq h, x; - for (int i = 0; i < JUBJUB_FIELD_BYTES; i++) { - h[i] = r[i]; - x[i] = h[i] ^ a[i]; - x[i] &= mask; - r[i] = r[i] ^ x[i]; - } + uint8_t b = bit & 0x01; + uint8_t mask = (uint8_t)(-(int8_t)b); + jubjub_fq h, x; + for (int i = 0; i < JUBJUB_FIELD_BYTES; i++) { + h[i] = r[i]; + x[i] = h[i] ^ a[i]; + x[i] &= mask; + r[i] = r[i] ^ x[i]; + } } zxerr_t jubjub_field_sqrt(jubjub_fq r, const jubjub_fq a) { - jubjub_fq w, x, b, z; - jubjub_field_pow_t(w, a); - - uint8_t v = 32; - jubjub_field_mult(x, a, w); - jubjub_field_mult(b, x, w); - jubjub_field_copy(z, JUBJUB_FQ_ROOT_OF_UNITY); - jubjub_fq tmp; - //uint8_t index = 0; - for (uint8_t max_v = 32; max_v >= 1; max_v--) { - uint8_t k = 1; - jubjub_field_square(tmp, b); - uint8_t j_less_than_v = 1; - for (uint8_t j = 2; j < max_v; j++) { - uint8_t tmp_is_one = jubjub_field_is_equal(tmp, JUBJUB_FQ_ONE); - jubjub_fq squared; - jubjub_field_copy(squared, z); - jubjub_field_cmov(squared, tmp, !tmp_is_one); - jubjub_field_square(squared, squared); - jubjub_field_cmov(tmp, squared, !tmp_is_one); - jubjub_fq new_z; - jubjub_field_copy(new_z, squared); - jubjub_field_cmov(new_z, z, !tmp_is_one); - j_less_than_v &= !(j == v); - u8_cmov(&k, j, !tmp_is_one); - jubjub_field_cmov(z, new_z, j_less_than_v); - } - - jubjub_fq result; - jubjub_field_mult(result, x, z); - uint8_t b_is_one = jubjub_field_is_equal(b, JUBJUB_FQ_ONE); - - jubjub_field_cmov(x, result, !b_is_one); - jubjub_field_square(z, z); - jubjub_field_mult(b, b, z); - v = k; + jubjub_fq w, x, b, z; + jubjub_field_pow_t(w, a); + + uint8_t v = 32; + jubjub_field_mult(x, a, w); + jubjub_field_mult(b, x, w); + jubjub_field_copy(z, JUBJUB_FQ_ROOT_OF_UNITY); + jubjub_fq tmp; + // uint8_t index = 0; + for (uint8_t max_v = 32; max_v >= 1; max_v--) { + uint8_t k = 1; + jubjub_field_square(tmp, b); + uint8_t j_less_than_v = 1; + for (uint8_t j = 2; j < max_v; j++) { + uint8_t tmp_is_one = jubjub_field_is_equal(tmp, JUBJUB_FQ_ONE); + jubjub_fq squared; + jubjub_field_copy(squared, z); + jubjub_field_cmov(squared, tmp, !tmp_is_one); + jubjub_field_square(squared, squared); + jubjub_field_cmov(tmp, squared, !tmp_is_one); + jubjub_fq new_z; + jubjub_field_copy(new_z, squared); + jubjub_field_cmov(new_z, z, !tmp_is_one); + j_less_than_v &= !(j == v); + u8_cmov(&k, j, !tmp_is_one); + jubjub_field_cmov(z, new_z, j_less_than_v); } - jubjub_field_square(w, x); - uint8_t correct = jubjub_field_is_equal(w, a); + jubjub_fq result; + jubjub_field_mult(result, x, z); + uint8_t b_is_one = jubjub_field_is_equal(b, JUBJUB_FQ_ONE); - if (!correct) { - return zxerr_unknown; - } + jubjub_field_cmov(x, result, !b_is_one); + jubjub_field_square(z, z); + jubjub_field_mult(b, b, z); + v = k; + } + + jubjub_field_square(w, x); + uint8_t correct = jubjub_field_is_equal(w, a); + + if (!correct) { + return zxerr_unknown; + } - jubjub_field_copy(r, x); - return zxerr_ok; + jubjub_field_copy(r, x); + return zxerr_ok; } -void jubjub_extendedpoint_cmov(jubjub_extendedpoint *r, jubjub_extendedpoint p, unsigned int bit) { - jubjub_field_cmov(r->U, p.U, bit); - jubjub_field_cmov(r->V, p.V, bit); - jubjub_field_cmov(r->Z, p.Z, bit); - jubjub_field_cmov(r->T1, p.T1, bit); - jubjub_field_cmov(r->T1, p.T2, bit); +void jubjub_extendedpoint_cmov(jubjub_extendedpoint *r, jubjub_extendedpoint p, + unsigned int bit) { + jubjub_field_cmov(r->U, p.U, bit); + jubjub_field_cmov(r->V, p.V, bit); + jubjub_field_cmov(r->Z, p.Z, bit); + jubjub_field_cmov(r->T1, p.T1, bit); + jubjub_field_cmov(r->T1, p.T2, bit); } -void jubjub_extendedpoint_normalize(jubjub_extendedpoint *r, jubjub_extendedpoint p) { - jubjub_fq zinv; - jubjub_field_inverse(zinv, r->Z); - jubjub_field_one(r->Z); - jubjub_field_mult(r->U, p.U, zinv); - jubjub_field_mult(r->V, p.V, zinv); - jubjub_field_copy(r->T1, p.U); - jubjub_field_copy(r->T2, p.V); +void jubjub_extendedpoint_normalize(jubjub_extendedpoint *r, + jubjub_extendedpoint p) { + jubjub_fq zinv; + jubjub_field_inverse(zinv, r->Z); + jubjub_field_one(r->Z); + jubjub_field_mult(r->U, p.U, zinv); + jubjub_field_mult(r->V, p.V, zinv); + jubjub_field_copy(r->T1, p.U); + jubjub_field_copy(r->T2, p.V); } void jubjub_extendedpoint_add(jubjub_extendedpoint *r, jubjub_extendedpoint p) { - //jubjub_extendedpoint np; - //jubjub_extendedpoint_normalize(&np, p); - //extendednielspoint - jubjub_fq v_minus_u, v_plus_u, t2d; - - jubjub_field_add(v_plus_u, p.V, p.U); - jubjub_field_sub(v_minus_u, p.V, p.U); - jubjub_field_mult(t2d, p.T1, p.T2); - jubjub_field_mult(t2d, t2d, JUBJUB_FQ_EDWARDS_2D); - - jubjub_fq a, b, c, d; - - jubjub_field_sub(a, r->V, r->U); - jubjub_field_mult(a, a, v_minus_u); - - jubjub_field_add(b, r->V, r->U); - jubjub_field_mult(b, b, v_plus_u); - - jubjub_field_mult(c, r->T1, r->T2); - jubjub_field_mult(c, c, t2d); - - jubjub_field_mult(d, r->Z, p.Z); - jubjub_field_double(d, d); - - //completed point - jubjub_fq u, v, z, t; - jubjub_field_sub(u, b, a); - jubjub_field_add(v, b, a); - jubjub_field_add(z, d, c); - jubjub_field_sub(t, d, c); - - //completed point to extended - jubjub_field_mult(r->U, u, t); - jubjub_field_mult(r->V, v, z); - jubjub_field_mult(r->Z, t, z); - jubjub_field_copy(r->T1, u); - jubjub_field_copy(r->T2, v); - + // jubjub_extendedpoint np; + // jubjub_extendedpoint_normalize(&np, p); + // extendednielspoint + jubjub_fq v_minus_u, v_plus_u, t2d; + + jubjub_field_add(v_plus_u, p.V, p.U); + jubjub_field_sub(v_minus_u, p.V, p.U); + jubjub_field_mult(t2d, p.T1, p.T2); + jubjub_field_mult(t2d, t2d, JUBJUB_FQ_EDWARDS_2D); + + jubjub_fq a, b, c, d; + + jubjub_field_sub(a, r->V, r->U); + jubjub_field_mult(a, a, v_minus_u); + + jubjub_field_add(b, r->V, r->U); + jubjub_field_mult(b, b, v_plus_u); + + jubjub_field_mult(c, r->T1, r->T2); + jubjub_field_mult(c, c, t2d); + + jubjub_field_mult(d, r->Z, p.Z); + jubjub_field_double(d, d); + + // completed point + jubjub_fq u, v, z, t; + jubjub_field_sub(u, b, a); + jubjub_field_add(v, b, a); + jubjub_field_add(z, d, c); + jubjub_field_sub(t, d, c); + + // completed point to extended + jubjub_field_mult(r->U, u, t); + jubjub_field_mult(r->V, v, z); + jubjub_field_mult(r->Z, t, z); + jubjub_field_copy(r->T1, u); + jubjub_field_copy(r->T2, v); } -void jubjub_extendedpoint_double(jubjub_extendedpoint *r, jubjub_extendedpoint p) { - - jubjub_fq uu, vv; - jubjub_fq zz2, uv2; - jubjub_fq vv_plus_uu, vv_minus_uu; +void jubjub_extendedpoint_double(jubjub_extendedpoint *r, + jubjub_extendedpoint p) { - jubjub_field_square(uu, p.U); - jubjub_field_square(vv, p.V); + jubjub_fq uu, vv; + jubjub_fq zz2, uv2; + jubjub_fq vv_plus_uu, vv_minus_uu; - jubjub_field_square(zz2, p.Z); - jubjub_field_double(zz2, zz2); + jubjub_field_square(uu, p.U); + jubjub_field_square(vv, p.V); - jubjub_field_add(uv2, p.U, p.V); - jubjub_field_square(uv2, uv2); + jubjub_field_square(zz2, p.Z); + jubjub_field_double(zz2, zz2); - jubjub_field_add(vv_plus_uu, vv, uu); - jubjub_field_sub(vv_minus_uu, vv, uu); + jubjub_field_add(uv2, p.U, p.V); + jubjub_field_square(uv2, uv2); - //completed point - jubjub_fq u, v, z, t; - jubjub_field_sub(u, uv2, vv_plus_uu); - jubjub_field_copy(v, vv_plus_uu); - jubjub_field_copy(z, vv_minus_uu); - jubjub_field_sub(t, zz2, vv_minus_uu); + jubjub_field_add(vv_plus_uu, vv, uu); + jubjub_field_sub(vv_minus_uu, vv, uu); + // completed point + jubjub_fq u, v, z, t; + jubjub_field_sub(u, uv2, vv_plus_uu); + jubjub_field_copy(v, vv_plus_uu); + jubjub_field_copy(z, vv_minus_uu); + jubjub_field_sub(t, zz2, vv_minus_uu); - //completed point to extended - jubjub_field_mult(r->U, u, t); - jubjub_field_mult(r->V, v, z); - jubjub_field_mult(r->Z, t, z); - jubjub_field_copy(r->T1, u); - jubjub_field_copy(r->T2, v); - + // completed point to extended + jubjub_field_mult(r->U, u, t); + jubjub_field_mult(r->V, v, z); + jubjub_field_mult(r->Z, t, z); + jubjub_field_copy(r->T1, u); + jubjub_field_copy(r->T2, v); } -void jubjub_extendedpoint_scalarmult(jubjub_extendedpoint *r, jubjub_fr scalar) { - jubjub_extendedpoint p, dummy; - MEMCPY(&p, &JUBJUB_ID, sizeof(jubjub_extendedpoint)); - //skip the first 4 bits as they are always 0 - for (int i = 4; i < 8 * JUBJUB_SCALAR_BYTES; i++) { - uint8_t di = (scalar[i / 8] >> (7 - (i % 8))) & 0x01; - jubjub_extendedpoint_double(&p, p); - MEMCPY(&dummy, &p, sizeof(jubjub_extendedpoint)); - jubjub_extendedpoint_add(&dummy, *r); - jubjub_extendedpoint_cmov(&p, dummy, di); - } - MEMCPY(r, &p, sizeof(jubjub_extendedpoint)); +void jubjub_extendedpoint_scalarmult(jubjub_extendedpoint *r, + jubjub_fr scalar) { + jubjub_extendedpoint p, dummy; + MEMCPY(&p, &JUBJUB_ID, sizeof(jubjub_extendedpoint)); + // skip the first 4 bits as they are always 0 + for (int i = 4; i < 8 * JUBJUB_SCALAR_BYTES; i++) { + uint8_t di = (scalar[i / 8] >> (7 - (i % 8))) & 0x01; + jubjub_extendedpoint_double(&p, p); + MEMCPY(&dummy, &p, sizeof(jubjub_extendedpoint)); + jubjub_extendedpoint_add(&dummy, *r); + jubjub_extendedpoint_cmov(&p, dummy, di); + } + MEMCPY(r, &p, sizeof(jubjub_extendedpoint)); } void jubjub_extendedpoint_tobytes(uint8_t *s, jubjub_extendedpoint p) { - jubjub_fq x, y, zinv; - jubjub_field_inverse(zinv, p.Z); - jubjub_field_mult(x, p.U, zinv); - jubjub_field_mult(y, p.V, zinv); + jubjub_fq x, y, zinv; + jubjub_field_inverse(zinv, p.Z); + jubjub_field_mult(x, p.U, zinv); + jubjub_field_mult(y, p.V, zinv); - MEMCPY(s, y, sizeof(jubjub_fq)); - s[0] |= (x[31] << 7); - SWAP_ENDIAN_BYTES(&s[0]); + MEMCPY(s, y, sizeof(jubjub_fq)); + s[0] |= (x[31] << 7); + SWAP_ENDIAN_BYTES(&s[0]); } zxerr_t jubjub_extendedpoint_frombytes(jubjub_extendedpoint *p, uint8_t *s) { - uint8_t b[JUBJUB_FIELD_BYTES]; - MEMCPY(b, s, JUBJUB_FIELD_BYTES); - SWAP_ENDIAN_BYTES(&b[0]); - - uint8_t sign = b[0] >> 7; - b[0] &= 0x7f; - - jubjub_fq v, v2, v3, u; - - jubjub_field_frombytes(v, b); - jubjub_field_square(v2, v); - jubjub_field_copy(v3, v2); - jubjub_field_mult(v2, v2, JUBJUB_FQ_EDWARDS_D); - jubjub_field_add(v2, v2, JUBJUB_FQ_ONE); - - if (jubjub_field_iszero(v2)) { - return zxerr_unknown; - } - - jubjub_field_inverse(v2, v2); - jubjub_field_sub(v3, v3, JUBJUB_FQ_ONE); - jubjub_field_mult(v3, v3, v2); - if (jubjub_field_sqrt(u, v3) != zxerr_ok) { - return zxerr_unknown; - } - - uint8_t flip_sign = (u[JUBJUB_FIELD_BYTES - 1] ^ sign) & 1; - jubjub_fq u_neg; - jubjub_field_negate(u_neg, u); - jubjub_field_cmov(u, u_neg, flip_sign); - - jubjub_field_copy(p->U, u); - jubjub_field_copy(p->V, v); - jubjub_field_copy(p->Z, JUBJUB_FQ_ONE); - jubjub_field_copy(p->T1, u); - jubjub_field_copy(p->T2, v); - return zxerr_ok; + uint8_t b[JUBJUB_FIELD_BYTES]; + MEMCPY(b, s, JUBJUB_FIELD_BYTES); + SWAP_ENDIAN_BYTES(&b[0]); + + uint8_t sign = b[0] >> 7; + b[0] &= 0x7f; + + jubjub_fq v, v2, v3, u; + + jubjub_field_frombytes(v, b); + jubjub_field_square(v2, v); + jubjub_field_copy(v3, v2); + jubjub_field_mult(v2, v2, JUBJUB_FQ_EDWARDS_D); + jubjub_field_add(v2, v2, JUBJUB_FQ_ONE); + + if (jubjub_field_iszero(v2)) { + return zxerr_unknown; + } + + jubjub_field_inverse(v2, v2); + jubjub_field_sub(v3, v3, JUBJUB_FQ_ONE); + jubjub_field_mult(v3, v3, v2); + if (jubjub_field_sqrt(u, v3) != zxerr_ok) { + return zxerr_unknown; + } + + uint8_t flip_sign = (u[JUBJUB_FIELD_BYTES - 1] ^ sign) & 1; + jubjub_fq u_neg; + jubjub_field_negate(u_neg, u); + jubjub_field_cmov(u, u_neg, flip_sign); + + jubjub_field_copy(p->U, u); + jubjub_field_copy(p->V, v); + jubjub_field_copy(p->Z, JUBJUB_FQ_ONE); + jubjub_field_copy(p->T1, u); + jubjub_field_copy(p->T2, v); + return zxerr_ok; } diff --git a/app/src/jubjub.h b/app/src/jubjub.h index dadb4a9a..e3364db7 100644 --- a/app/src/jubjub.h +++ b/app/src/jubjub.h @@ -1,55 +1,58 @@ /******************************************************************************* -* (c) 2021 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2021 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include -#define JUBJUB_SCALAR_BYTES 32 -#define JUBJUB_FIELD_BYTES 32 +#define JUBJUB_SCALAR_BYTES 32 +#define JUBJUB_FIELD_BYTES 32 typedef unsigned char jubjub_fr[JUBJUB_SCALAR_BYTES]; typedef unsigned char jubjub_fq[JUBJUB_FIELD_BYTES]; typedef struct { - jubjub_fq U; - jubjub_fq V; - jubjub_fq Z; - jubjub_fq T1; - jubjub_fq T2; + jubjub_fq U; + jubjub_fq V; + jubjub_fq Z; + jubjub_fq T1; + jubjub_fq T2; } jubjub_extendedpoint; extern const jubjub_extendedpoint JUBJUB_GEN; -#define SWAP_BYTES(x, y, tmp) { \ - tmp = x; \ - x = y; \ - y = tmp;\ -} - -#define SWAP_ENDIAN_U64(x, tmp) { \ - SWAP_BYTES(*x, *(x + 7), tmp); \ -SWAP_BYTES(*(x+1), *(x + 6), tmp); \ -SWAP_BYTES(*(x+2), *(x + 5), tmp); \ -SWAP_BYTES(*(x+3), *(x + 4), tmp); \ -} - -#define SWAP_ENDIAN_BYTES(x) { \ - uint8_t tmp = 0; \ - for (int i = 0; i < 32/2; i++){ \ - SWAP_BYTES(*(x + i), *(x + (32-1-i)), tmp); \ - } \ -} +#define SWAP_BYTES(x, y, tmp) \ + { \ + tmp = x; \ + x = y; \ + y = tmp; \ + } + +#define SWAP_ENDIAN_U64(x, tmp) \ + { \ + SWAP_BYTES(*x, *(x + 7), tmp); \ + SWAP_BYTES(*(x + 1), *(x + 6), tmp); \ + SWAP_BYTES(*(x + 2), *(x + 5), tmp); \ + SWAP_BYTES(*(x + 3), *(x + 4), tmp); \ + } + +#define SWAP_ENDIAN_BYTES(x) \ + { \ + uint8_t tmp = 0; \ + for (int i = 0; i < 32 / 2; i++) { \ + SWAP_BYTES(*(x + i), *(x + (32 - 1 - i)), tmp); \ + } \ + } void jubjub_extendedpoint_tobytes(uint8_t *s, jubjub_extendedpoint p); diff --git a/app/src/key.c b/app/src/key.c index 9683b290..815454ed 100644 --- a/app/src/key.c +++ b/app/src/key.c @@ -1,88 +1,87 @@ /******************************************************************************* -* (c) 2020 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2020 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ -#include +#include "actions.h" +#include "app_mode.h" #include "coin.h" +#include "crypto.h" #include "zxerror.h" -#include "zxmacros.h" #include "zxformat.h" -#include "app_mode.h" -#include "crypto.h" -#include "actions.h" +#include "zxmacros.h" +#include zxerr_t key_getNumItems(uint8_t *num_items) { - zemu_log_stack("key_getNumItems"); - *num_items = 1; - if (app_mode_expert()) { - *num_items = 2; - } - return zxerr_ok; + zemu_log_stack("key_getNumItems"); + *num_items = 1; + if (app_mode_expert()) { + *num_items = 2; + } + return zxerr_ok; } -zxerr_t key_getItem(int8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outVal, uint16_t outValLen, - uint8_t pageIdx, uint8_t *pageCount) { - snprintf(outKey, outKeyLen, "?"); - snprintf(outVal, outValLen, "?"); +zxerr_t key_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, + char *outVal, uint16_t outValLen, uint8_t pageIdx, + uint8_t *pageCount) { + snprintf(outKey, outKeyLen, "?"); + snprintf(outVal, outValLen, "?"); - zemu_log_stack("key_getItem"); - switch (displayIdx) { - case 0: { - zemu_log_stack("case 0"); - char tmpBuffer[100]; - MEMZERO(tmpBuffer, sizeof(tmpBuffer)); - switch (key_state.kind) { - case key_ovk: - snprintf(outKey, outKeyLen, "Send OVK?"); - array_to_hexstr(tmpBuffer, sizeof(tmpBuffer), G_io_apdu_buffer, 32); - pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); - return zxerr_ok; - case key_ivk: - snprintf(outKey, outKeyLen, "Send IVK?"); - array_to_hexstr(tmpBuffer, sizeof(tmpBuffer), G_io_apdu_buffer, 32); - pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); - return zxerr_ok; - case key_fvk: - snprintf(outKey, outKeyLen, "Send FVK?\n"); - array_to_hexstr(tmpBuffer, sizeof(tmpBuffer), G_io_apdu_buffer, 32); - pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); - return zxerr_ok; - case nf: - zemu_log_stack("Send NF?"); - snprintf(outKey, outKeyLen, "Send NF?"); - array_to_hexstr(tmpBuffer, sizeof(tmpBuffer), G_io_apdu_buffer, 32); - pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); - return zxerr_ok; - default: - return zxerr_unknown; - } - } - case 1: { - if (!app_mode_expert()) { - return zxerr_no_data; - } - - snprintf(outKey, outKeyLen, "Your Path"); - char buffer[300]; - bip32_to_str(buffer, sizeof(buffer), hdPath, HDPATH_LEN_DEFAULT); - pageString(outVal, outValLen, buffer, pageIdx, pageCount); - return zxerr_ok; - } - default: - return zxerr_no_data; + zemu_log_stack("key_getItem"); + switch (displayIdx) { + case 0: { + zemu_log_stack("case 0"); + char tmpBuffer[100]; + MEMZERO(tmpBuffer, sizeof(tmpBuffer)); + switch (key_state.kind) { + case key_ovk: + snprintf(outKey, outKeyLen, "Send OVK?"); + array_to_hexstr(tmpBuffer, sizeof(tmpBuffer), G_io_apdu_buffer, 32); + pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); + return zxerr_ok; + case key_ivk: + snprintf(outKey, outKeyLen, "Send IVK?"); + array_to_hexstr(tmpBuffer, sizeof(tmpBuffer), G_io_apdu_buffer, 32); + pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); + return zxerr_ok; + case key_fvk: + snprintf(outKey, outKeyLen, "Send FVK?\n"); + array_to_hexstr(tmpBuffer, sizeof(tmpBuffer), G_io_apdu_buffer, 32); + pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); + return zxerr_ok; + case nf: + zemu_log_stack("Send NF?"); + snprintf(outKey, outKeyLen, "Send NF?"); + array_to_hexstr(tmpBuffer, sizeof(tmpBuffer), G_io_apdu_buffer, 32); + pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); + return zxerr_ok; + default: + return zxerr_unknown; + } + } + case 1: { + if (!app_mode_expert()) { + return zxerr_no_data; } + + snprintf(outKey, outKeyLen, "Your Path"); + char buffer[300]; + bip32_to_str(buffer, sizeof(buffer), hdPath, HDPATH_LEN_DEFAULT); + pageString(outVal, outValLen, buffer, pageIdx, pageCount); + return zxerr_ok; + } + default: + return zxerr_no_data; + } } diff --git a/app/src/key.h b/app/src/key.h index 56d3b399..ffef4036 100644 --- a/app/src/key.h +++ b/app/src/key.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2020 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2020 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -24,10 +24,9 @@ extern "C" { zxerr_t key_getNumItems(uint8_t *num_items); /// Gets an specific item from the address view (including paging) -zxerr_t key_getItem(int8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outValue, uint16_t outValueLen, - uint8_t pageIdx, uint8_t *pageCount); +zxerr_t key_getItem(int8_t displayIdx, char *outKey, uint16_t outKeyLen, + char *outValue, uint16_t outValueLen, uint8_t pageIdx, + uint8_t *pageCount); #ifdef __cplusplus } diff --git a/app/src/nvdata.c b/app/src/nvdata.c index c60ce0de..90d311e3 100644 --- a/app/src/nvdata.c +++ b/app/src/nvdata.c @@ -1,46 +1,43 @@ /******************************************************************************* -* (c) 2020 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2020 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ -#include "os.h" -#include "cx.h" -#include "coin.h" -#include "app_main.h" #include "nvdata.h" +#include "app_main.h" +#include "coin.h" #include "constants.h" +#include "cx.h" +#include "os.h" #include "view.h" -t_inlist_t NV_CONST -N_t_inlist_impl __attribute__ ((aligned(64))); +t_inlist_t NV_CONST N_t_inlist_impl __attribute__((aligned(64))); #define N_t_inlist (*(NV_VOLATILE t_inlist_t *)PIC(&N_t_inlist_impl)) -t_outlist_t NV_CONST -N_t_outlist_impl __attribute__ ((aligned(64))); +t_outlist_t NV_CONST N_t_outlist_impl __attribute__((aligned(64))); #define N_t_outlist (*(NV_VOLATILE t_outlist_t *)PIC(&N_t_outlist_impl)) -spendlist_t NV_CONST -N_spendlist_impl __attribute__ ((aligned(64))); +spendlist_t NV_CONST N_spendlist_impl __attribute__((aligned(64))); #define N_spendlist (*(NV_VOLATILE spendlist_t *)PIC(&N_spendlist_impl)) -outputlist_t NV_CONST -N_outputlist_impl __attribute__ ((aligned(64))); +outputlist_t NV_CONST N_outputlist_impl __attribute__((aligned(64))); #define N_outputlist (*(NV_VOLATILE outputlist_t *)PIC(&N_outputlist_impl)) -transaction_info_t NV_CONST -N_transaction_info_impl __attribute__ ((aligned(64))); -#define N_transactioninfo (*(NV_VOLATILE transaction_info_t *)PIC(&N_transaction_info_impl)) +transaction_info_t NV_CONST N_transaction_info_impl + __attribute__((aligned(64))); +#define N_transactioninfo \ + (*(NV_VOLATILE transaction_info_t *)PIC(&N_transaction_info_impl)) transaction_header_t transaction_header; @@ -50,351 +47,346 @@ transaction_header_t transaction_header; ////////////////////////////////////////////////////////////// zxerr_t t_inlist_append_item(uint32_t *p, uint8_t *script, uint64_t v) { - zemu_log_stack("let's append"); - if (transaction_header.t_in_len >= T_IN_LIST_SIZE) { - return zxerr_unknown; - } + zemu_log_stack("let's append"); + if (transaction_header.t_in_len >= T_IN_LIST_SIZE) { + return zxerr_unknown; + } - transaction_header.total_value += v; + transaction_header.total_value += v; - t_input_item_t newitem; - MEMCPY(newitem.path, (uint8_t *)p, PATH_SIZE * sizeof(uint32_t)); - MEMCPY(newitem.script, script, SCRIPT_SIZE); - newitem.value = v; + t_input_item_t newitem; + MEMCPY(newitem.path, (uint8_t *)p, PATH_SIZE * sizeof(uint32_t)); + MEMCPY(newitem.script, script, SCRIPT_SIZE); + newitem.value = v; - MEMCPY_NV((void *) &N_t_inlist.items[transaction_header.t_in_len], - &newitem, sizeof(t_input_item_t)); + MEMCPY_NV((void *)&N_t_inlist.items[transaction_header.t_in_len], &newitem, + sizeof(t_input_item_t)); - transaction_header.t_in_len += 1; - zemu_log_stack("appended"); - return zxerr_ok; + transaction_header.t_in_len += 1; + zemu_log_stack("appended"); + return zxerr_ok; } t_input_item_t *t_inlist_retrieve_item(uint8_t i) { - if (transaction_header.t_in_len < i) { - return NULL; - } else { - return (t_input_item_t *) &N_t_inlist.items[i]; - } + if (transaction_header.t_in_len < i) { + return NULL; + } else { + return (t_input_item_t *)&N_t_inlist.items[i]; + } } zxerr_t t_outlist_append_item(uint8_t *addr, uint64_t v) { - if (transaction_header.t_out_len >= T_OUT_LIST_SIZE) { - return zxerr_unknown; - } + if (transaction_header.t_out_len >= T_OUT_LIST_SIZE) { + return zxerr_unknown; + } - transaction_header.total_value -= v; + transaction_header.total_value -= v; - t_output_item_t newitem; - MEMCPY(newitem.address, addr, SCRIPT_SIZE); - newitem.value = v; + t_output_item_t newitem; + MEMCPY(newitem.address, addr, SCRIPT_SIZE); + newitem.value = v; - MEMCPY_NV((void *) &N_t_outlist.items[transaction_header.t_out_len], - &newitem, sizeof(t_output_item_t)); + MEMCPY_NV((void *)&N_t_outlist.items[transaction_header.t_out_len], &newitem, + sizeof(t_output_item_t)); - transaction_header.t_out_len += 1; - return zxerr_ok; + transaction_header.t_out_len += 1; + return zxerr_ok; } t_output_item_t *t_outlist_retrieve_item(uint8_t i) { - if (transaction_header.t_out_len < i) { - return NULL; - } else { - return (t_output_item_t *) &N_t_outlist.items[i]; - } + if (transaction_header.t_out_len < i) { + return NULL; + } else { + return (t_output_item_t *)&N_t_outlist.items[i]; + } } -uint8_t t_inlist_len() { - return transaction_header.t_in_len; -} +uint8_t t_inlist_len() { return transaction_header.t_in_len; } // Returns the list of all transparent input amounts. -uint64_t t_inlist_retrieve_item_amount(uint8_t i){ - return N_t_inlist.items[i].value; +uint64_t t_inlist_retrieve_item_amount(uint8_t i) { + return N_t_inlist.items[i].value; } -void t_inlist_retrieve_item_script(uint8_t i, uint8_t *output){ - MEMCPY(output, (const void *) N_t_inlist.items[i].script, SCRIPT_SIZE); +void t_inlist_retrieve_item_script(uint8_t i, uint8_t *output) { + MEMCPY(output, (const void *)N_t_inlist.items[i].script, SCRIPT_SIZE); } -uint8_t t_outlist_len() { - return transaction_header.t_out_len; -} +uint8_t t_outlist_len() { return transaction_header.t_out_len; } bool transparent_signatures_more_extract() { - return transaction_header.t_sign_index > 0; + return transaction_header.t_sign_index > 0; } - zxerr_t transparent_signatures_append(uint8_t *signature) { - if (transaction_header.t_sign_index >= transaction_header.t_in_len) { - return zxerr_unknown; - } - MEMCPY_NV((void *) &N_transactioninfo.transparent_signatures[transaction_header.t_sign_index], + if (transaction_header.t_sign_index >= transaction_header.t_in_len) { + return zxerr_unknown; + } + MEMCPY_NV((void *)&N_transactioninfo + .transparent_signatures[transaction_header.t_sign_index], signature, SIGNATURE_SIZE); - transaction_header.t_sign_index++; - return zxerr_ok; + transaction_header.t_sign_index++; + return zxerr_ok; } zxerr_t get_next_transparent_signature(uint8_t *result) { - uint8_t index = transaction_header.t_in_len - transaction_header.t_sign_index; - if (transaction_header.t_in_len <= index || index < 0) { - return zxerr_unknown; - } - MEMCPY(result, (void *) &N_transactioninfo.transparent_signatures[index], SIGNATURE_SIZE); - transaction_header.t_sign_index--; - if (!transparent_signatures_more_extract() && !spend_signatures_more_extract()) { - transaction_reset(); - view_idle_show(0, NULL); - } - return zxerr_ok; + uint8_t index = transaction_header.t_in_len - transaction_header.t_sign_index; + if (transaction_header.t_in_len <= index || index < 0) { + return zxerr_unknown; + } + MEMCPY(result, (void *)&N_transactioninfo.transparent_signatures[index], + SIGNATURE_SIZE); + transaction_header.t_sign_index--; + if (!transparent_signatures_more_extract() && + !spend_signatures_more_extract()) { + transaction_reset(); + view_idle_show(0, NULL); + } + return zxerr_ok; } bool spend_signatures_more_extract() { - return transaction_header.spends_sign_index > 0; + return transaction_header.spends_sign_index > 0; } zxerr_t spend_signatures_append(uint8_t *signature) { - if (transaction_header.spends_sign_index >= transaction_header.spendlist_len) { - return zxerr_unknown; - } + if (transaction_header.spends_sign_index >= + transaction_header.spendlist_len) { + return zxerr_unknown; + } - MEMCPY_NV((void *) &N_transactioninfo.spend_signatures[transaction_header.spends_sign_index], + MEMCPY_NV((void *)&N_transactioninfo + .spend_signatures[transaction_header.spends_sign_index], signature, SIGNATURE_SIZE); - transaction_header.spends_sign_index++; - return zxerr_ok; + transaction_header.spends_sign_index++; + return zxerr_ok; } zxerr_t get_next_spend_signature(uint8_t *result) { - uint8_t index = transaction_header.spendlist_len - transaction_header.spends_sign_index; - if (transaction_header.spendlist_len <= index || index < 0) { - return zxerr_unknown; - } - MEMCPY(result, (void *) &N_transactioninfo.spend_signatures[index], SIGNATURE_SIZE); - transaction_header.spends_sign_index--; - if (!transparent_signatures_more_extract() && !spend_signatures_more_extract()) { - transaction_reset(); - view_idle_show(0, NULL); - } - return zxerr_ok; + uint8_t index = + transaction_header.spendlist_len - transaction_header.spends_sign_index; + if (transaction_header.spendlist_len <= index || index < 0) { + return zxerr_unknown; + } + MEMCPY(result, (void *)&N_transactioninfo.spend_signatures[index], + SIGNATURE_SIZE); + transaction_header.spends_sign_index--; + if (!transparent_signatures_more_extract() && + !spend_signatures_more_extract()) { + transaction_reset(); + view_idle_show(0, NULL); + } + return zxerr_ok; } void transaction_reset() { - MEMZERO(&transaction_header, sizeof(transaction_header_t)); - zeroize_flashstorage(); + MEMZERO(&transaction_header, sizeof(transaction_header_t)); + zeroize_flashstorage(); } -bool spendlist_is_active() { - return transaction_header.spendlist_len > 0; -} +bool spendlist_is_active() { return transaction_header.spendlist_len > 0; } -zxerr_t spendlist_append_item(uint32_t p, uint64_t v, uint8_t *div, uint8_t *pkd, uint8_t *rcm, uint8_t *alpha) { - if (transaction_header.spendlist_len >= SPEND_LIST_SIZE) { - return zxerr_unknown; - } +zxerr_t spendlist_append_item(uint32_t p, uint64_t v, uint8_t *div, + uint8_t *pkd, uint8_t *rcm, uint8_t *alpha) { + if (transaction_header.spendlist_len >= SPEND_LIST_SIZE) { + return zxerr_unknown; + } - transaction_header.sapling_value += v; - transaction_header.total_value += v; - uint32_t path = p | 0x80000000; + transaction_header.sapling_value += v; + transaction_header.total_value += v; + uint32_t path = p | 0x80000000; - spend_item_t newitem; - newitem.path = path; - newitem.value = v; - MEMCPY(newitem.div, div, DIV_SIZE); - MEMCPY(newitem.pkd, pkd, PKD_SIZE); - MEMCPY(newitem.rcmvalue, rcm, RCM_SIZE); - MEMCPY(newitem.alpha, alpha, ALPHA_SIZE); + spend_item_t newitem; + newitem.path = path; + newitem.value = v; + MEMCPY(newitem.div, div, DIV_SIZE); + MEMCPY(newitem.pkd, pkd, PKD_SIZE); + MEMCPY(newitem.rcmvalue, rcm, RCM_SIZE); + MEMCPY(newitem.alpha, alpha, ALPHA_SIZE); - MEMCPY_NV((void *) &N_spendlist.items[transaction_header.spendlist_len], + MEMCPY_NV((void *)&N_spendlist.items[transaction_header.spendlist_len], &newitem, sizeof(spend_item_t)); - transaction_header.spendlist_len += 1; - return zxerr_ok; + transaction_header.spendlist_len += 1; + return zxerr_ok; } 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]; - } + 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; - } + 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; + } } bool spendlist_more_extract() { - return transaction_header.spendlist_len > transaction_header.spenddata_extract_index; + return transaction_header.spendlist_len > + transaction_header.spenddata_extract_index; } -uint8_t spendlist_len() { - return transaction_header.spendlist_len; -} +uint8_t spendlist_len() { return transaction_header.spendlist_len; } -bool outputlist_is_active() { - return transaction_header.outputlist_len > 0; -} +bool outputlist_is_active() { return transaction_header.outputlist_len > 0; } -zxerr_t outputlist_append_item(uint8_t *d, uint8_t *pkd, uint64_t v, uint8_t memotype, uint8_t *ovk, uint8_t *rcmv, +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) { - return zxerr_unknown; - } - transaction_header.sapling_value -= v; - transaction_header.total_value -= v; - - output_item_t newitem; - newitem.value = v; - MEMCPY(newitem.rcmvalue, rcmv, RCM_V_SIZE); - MEMCPY(newitem.rseed, rseed, RSEED_SIZE); - MEMCPY(newitem.div, d, DIV_SIZE); - MEMCPY(newitem.pkd, pkd, PKD_SIZE); - MEMCPY(newitem.ovk, ovk, OVK_SET_SIZE); - newitem.memotype = memotype; - MEMCPY_NV((void *) &N_outputlist.items[transaction_header.outputlist_len], + if (transaction_header.outputlist_len >= OUTPUT_LIST_SIZE) { + return zxerr_unknown; + } + transaction_header.sapling_value -= v; + transaction_header.total_value -= v; + + output_item_t newitem; + newitem.value = v; + MEMCPY(newitem.rcmvalue, rcmv, RCM_V_SIZE); + MEMCPY(newitem.rseed, rseed, RSEED_SIZE); + MEMCPY(newitem.div, d, DIV_SIZE); + MEMCPY(newitem.pkd, pkd, PKD_SIZE); + MEMCPY(newitem.ovk, ovk, OVK_SET_SIZE); + newitem.memotype = memotype; + MEMCPY_NV((void *)&N_outputlist.items[transaction_header.outputlist_len], &newitem, sizeof(output_item_t)); - transaction_header.outputlist_len += 1; - return zxerr_ok; + transaction_header.outputlist_len += 1; + return zxerr_ok; } output_item_t *outputlist_retrieve_item(uint8_t i) { - if (transaction_header.outputlist_len < i) { - return NULL; - } else { - return (output_item_t *) &N_outputlist.items[i]; - } + if (transaction_header.outputlist_len < i) { + return NULL; + } else { + return (output_item_t *)&N_outputlist.items[i]; + } } output_item_t *outputlist_extract_next() { - if (transaction_header.outputlist_len <= transaction_header.outputdata_extract_index) { - return NULL; - } else { - output_item_t *result = (output_item_t *) &N_outputlist.items[transaction_header.outputdata_extract_index]; - transaction_header.outputdata_extract_index += 1; - return result; - } + if (transaction_header.outputlist_len <= + transaction_header.outputdata_extract_index) { + return NULL; + } else { + output_item_t *result = + (output_item_t *)&N_outputlist + .items[transaction_header.outputdata_extract_index]; + transaction_header.outputdata_extract_index += 1; + return result; + } } bool outputlist_more_extract() { - return transaction_header.outputlist_len > transaction_header.outputdata_extract_index; + return transaction_header.outputlist_len > + transaction_header.outputdata_extract_index; } -uint8_t outputlist_len() { - return transaction_header.outputlist_len; -} +uint8_t outputlist_len() { return transaction_header.outputlist_len; } // valueBalance is not the total value, but the // net value of Sapling Spend transfers minus Output transfers. // i.e. the contents of the Sapling value pool -int64_t get_valuebalance() { - return transaction_header.sapling_value; -} -uint64_t get_totalvalue() { - return transaction_header.total_value; -} -uint8_t get_state() { - return transaction_header.state; -} +int64_t get_valuebalance() { return transaction_header.sapling_value; } +uint64_t get_totalvalue() { return transaction_header.total_value; } +uint8_t get_state() { return transaction_header.state; } -void set_state(uint8_t state) { - transaction_header.state = state; -} +void set_state(uint8_t state) { transaction_header.state = state; } -void state_reset() { - transaction_header.state = STATE_INITIAL; -} +void state_reset() { transaction_header.state = STATE_INITIAL; } void zeroize_tin_data() { - uint32_t p[PATH_SIZE]; - uint8_t s[SCRIPT_SIZE]; - uint64_t v = 0; - MEMZERO(p, sizeof(p)); - MEMZERO(s, sizeof(s)); - transaction_header.t_in_len = 0; - for (int i = 0; i < T_IN_LIST_SIZE; i++) { - t_inlist_append_item(p, s, v); - } - transaction_header.t_in_len = 0; + uint32_t p[PATH_SIZE]; + uint8_t s[SCRIPT_SIZE]; + uint64_t v = 0; + MEMZERO(p, sizeof(p)); + MEMZERO(s, sizeof(s)); + transaction_header.t_in_len = 0; + for (int i = 0; i < T_IN_LIST_SIZE; i++) { + t_inlist_append_item(p, s, v); + } + transaction_header.t_in_len = 0; } void zeroize_tout_data() { - uint8_t s[SCRIPT_SIZE]; - uint64_t v = 0; - MEMZERO(s, sizeof(s)); - transaction_header.t_out_len = 0; - for (int i = 0; i < T_OUT_LIST_SIZE; i++) { - t_outlist_append_item(s, v); - } - transaction_header.t_out_len = 0; + uint8_t s[SCRIPT_SIZE]; + uint64_t v = 0; + MEMZERO(s, sizeof(s)); + transaction_header.t_out_len = 0; + for (int i = 0; i < T_OUT_LIST_SIZE; i++) { + t_outlist_append_item(s, v); + } + transaction_header.t_out_len = 0; } void zeroize_spend_data() { - uint32_t p = 0; - uint64_t v = 0; - uint8_t div[DIV_SIZE]; - uint8_t pkd[PKD_SIZE]; - uint8_t rcm[RCM_SIZE]; - uint8_t alpha[ALPHA_SIZE]; - MEMZERO(div, sizeof(div)); - MEMZERO(pkd, sizeof(pkd)); - MEMZERO(rcm, sizeof(rcm)); - MEMZERO(alpha, sizeof(alpha)); - transaction_header.spendlist_len = 0; - for (int i = 0; i < SPEND_LIST_SIZE; i++) { - spendlist_append_item(p, v, div, pkd, rcm, alpha); - } - transaction_header.spendlist_len = 0; + uint32_t p = 0; + uint64_t v = 0; + uint8_t div[DIV_SIZE]; + uint8_t pkd[PKD_SIZE]; + uint8_t rcm[RCM_SIZE]; + uint8_t alpha[ALPHA_SIZE]; + MEMZERO(div, sizeof(div)); + MEMZERO(pkd, sizeof(pkd)); + MEMZERO(rcm, sizeof(rcm)); + MEMZERO(alpha, sizeof(alpha)); + transaction_header.spendlist_len = 0; + for (int i = 0; i < SPEND_LIST_SIZE; i++) { + spendlist_append_item(p, v, div, pkd, rcm, alpha); + } + transaction_header.spendlist_len = 0; } void zeroize_output_data() { - uint64_t v = 0; - uint8_t div[DIV_SIZE]; - uint8_t pkd[PKD_SIZE]; - uint8_t ovk[OVK_SIZE]; - uint8_t rcmv[RCM_V_SIZE]; - uint8_t rseed[RSEED_SIZE]; - uint8_t memotype = 0x00; - MEMZERO(div, sizeof(div)); - MEMZERO(pkd, sizeof(pkd)); - MEMZERO(ovk, sizeof(ovk)); - MEMZERO(rcmv, sizeof(rcmv)); - MEMZERO(rseed, sizeof(rseed)); - transaction_header.outputlist_len = 0; - for (int i = 0; i < OUTPUT_LIST_SIZE; i++) { - outputlist_append_item(div, pkd, v, memotype, ovk, rcmv, rseed); - } - transaction_header.outputlist_len = 0; + uint64_t v = 0; + uint8_t div[DIV_SIZE]; + uint8_t pkd[PKD_SIZE]; + uint8_t ovk[OVK_SIZE]; + uint8_t rcmv[RCM_V_SIZE]; + uint8_t rseed[RSEED_SIZE]; + uint8_t memotype = 0x00; + MEMZERO(div, sizeof(div)); + MEMZERO(pkd, sizeof(pkd)); + MEMZERO(ovk, sizeof(ovk)); + MEMZERO(rcmv, sizeof(rcmv)); + MEMZERO(rseed, sizeof(rseed)); + transaction_header.outputlist_len = 0; + for (int i = 0; i < OUTPUT_LIST_SIZE; i++) { + outputlist_append_item(div, pkd, v, memotype, ovk, rcmv, rseed); + } + transaction_header.outputlist_len = 0; } void zeroize_signatures() { - uint8_t sig[SIGNATURE_SIZE]; - MEMZERO(sig, SIGNATURE_SIZE); - - transaction_header.t_sign_index = 0; - for (int i = 0; i < T_IN_LIST_SIZE; i++) { - transparent_signatures_append(sig); - } - transaction_header.t_sign_index = 0; - - transaction_header.spends_sign_index = 0; - for (int i = 0; i < T_IN_LIST_SIZE; i++) { - spend_signatures_append(sig); - } - transaction_header.spends_sign_index = 0; + uint8_t sig[SIGNATURE_SIZE]; + MEMZERO(sig, SIGNATURE_SIZE); + + transaction_header.t_sign_index = 0; + for (int i = 0; i < T_IN_LIST_SIZE; i++) { + transparent_signatures_append(sig); + } + transaction_header.t_sign_index = 0; + + transaction_header.spends_sign_index = 0; + for (int i = 0; i < T_IN_LIST_SIZE; i++) { + spend_signatures_append(sig); + } + transaction_header.spends_sign_index = 0; } void zeroize_flashstorage() { - zeroize_tin_data(); - zeroize_tout_data(); - zeroize_spend_data(); - zeroize_output_data(); - zeroize_signatures(); + zeroize_tin_data(); + zeroize_tout_data(); + zeroize_spend_data(); + zeroize_output_data(); + zeroize_signatures(); } diff --git a/app/src/nvdata.h b/app/src/nvdata.h index e9f36325..c89f92b2 100644 --- a/app/src/nvdata.h +++ b/app/src/nvdata.h @@ -1,89 +1,89 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once -#include "zxmacros.h" -#include -#include "zxerror.h" #include "coin.h" #include "constants.h" +#include "zxerror.h" +#include "zxmacros.h" +#include typedef struct { - uint32_t path[PATH_SIZE]; - uint8_t script[SCRIPT_SIZE]; - uint64_t value; + uint32_t path[PATH_SIZE]; + uint8_t script[SCRIPT_SIZE]; + uint64_t value; } t_input_item_t; typedef struct { - uint8_t address[SCRIPT_SIZE]; - uint64_t value; + uint8_t address[SCRIPT_SIZE]; + uint64_t value; } t_output_item_t; typedef struct { - t_input_item_t items[T_IN_LIST_SIZE]; + t_input_item_t items[T_IN_LIST_SIZE]; } t_inlist_t; typedef struct { - t_output_item_t items[T_OUT_LIST_SIZE]; + t_output_item_t items[T_OUT_LIST_SIZE]; } t_outlist_t; typedef struct { - uint32_t path; - uint64_t value; - uint8_t div[DIV_SIZE]; - uint8_t pkd[PKD_SIZE]; - uint8_t rcmvalue[RCM_SIZE]; - uint8_t alpha[ALPHA_SIZE]; + uint32_t path; + uint64_t value; + uint8_t div[DIV_SIZE]; + uint8_t pkd[PKD_SIZE]; + uint8_t rcmvalue[RCM_SIZE]; + uint8_t alpha[ALPHA_SIZE]; } spend_item_t; typedef struct { - uint64_t total_value; - int64_t sapling_value; - uint8_t state; - uint8_t t_in_len; - uint8_t t_out_len; - uint8_t spendlist_len; - uint8_t outputlist_len; - uint8_t spenddata_extract_index; - uint8_t outputdata_extract_index; - uint8_t spends_sign_index; - uint8_t t_sign_index; + uint64_t total_value; + int64_t sapling_value; + uint8_t state; + uint8_t t_in_len; + uint8_t t_out_len; + uint8_t spendlist_len; + uint8_t outputlist_len; + uint8_t spenddata_extract_index; + uint8_t outputdata_extract_index; + uint8_t spends_sign_index; + uint8_t t_sign_index; } transaction_header_t; typedef struct { - spend_item_t items[SPEND_LIST_SIZE]; + spend_item_t items[SPEND_LIST_SIZE]; } spendlist_t; typedef struct { - uint8_t div[DIV_SIZE]; - uint8_t pkd[PKD_SIZE]; - uint64_t value; - uint8_t memotype; - uint8_t rcmvalue[RCM_V_SIZE]; - uint8_t rseed[RSEED_SIZE]; - uint8_t ovk[OVK_SET_SIZE]; + uint8_t div[DIV_SIZE]; + uint8_t pkd[PKD_SIZE]; + uint64_t value; + uint8_t memotype; + uint8_t rcmvalue[RCM_V_SIZE]; + uint8_t rseed[RSEED_SIZE]; + uint8_t ovk[OVK_SET_SIZE]; } output_item_t; typedef struct { - output_item_t items[SPEND_LIST_SIZE]; + output_item_t items[SPEND_LIST_SIZE]; } outputlist_t; typedef struct { - uint8_t transparent_signatures[T_IN_LIST_SIZE][64]; - uint8_t spend_signatures[SPEND_LIST_SIZE][64]; + uint8_t transparent_signatures[T_IN_LIST_SIZE][64]; + uint8_t spend_signatures[SPEND_LIST_SIZE][64]; } transaction_info_t; #ifdef __cplusplus @@ -92,22 +92,22 @@ extern "C" { void transaction_reset(); -//statemachine API +// statemachine API uint8_t get_state(); void state_reset(); void set_state(uint8_t state); -#define STATE_INITIAL 0 -#define STATE_PROCESSED_INPUTS 1 -#define STATE_PROCESSED_SPEND_EXTRACTIONS 2 -#define STATE_PROCESSED_ALL_EXTRACTIONS 3 -#define STATE_CHECKING_ALL_TXDATA 4 -#define STATE_VERIFIED_ALL_TXDATA 5 -#define STATE_SIGNED_TX 6 +#define STATE_INITIAL 0 +#define STATE_PROCESSED_INPUTS 1 +#define STATE_PROCESSED_SPEND_EXTRACTIONS 2 +#define STATE_PROCESSED_ALL_EXTRACTIONS 3 +#define STATE_CHECKING_ALL_TXDATA 4 +#define STATE_VERIFIED_ALL_TXDATA 5 +#define STATE_SIGNED_TX 6 -//metadata flash api +// metadata flash api int64_t get_valuebalance(); uint64_t get_totalvalue(); @@ -126,7 +126,7 @@ zxerr_t spend_signatures_append(uint8_t *signature); zxerr_t get_next_spend_signature(uint8_t *result); -//transparent TxIN API +// transparent TxIN API zxerr_t t_inlist_append_item(uint32_t *p, uint8_t *script, uint64_t v); t_input_item_t *t_inlist_retrieve_item(uint8_t i); @@ -137,17 +137,18 @@ uint64_t t_inlist_retrieve_item_amount(uint8_t i); void t_inlist_retrieve_item_script(uint8_t i, uint8_t *output); -//transparent TXOUT API +// 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(); -//spendlist flashstorage API +// spendlist flashstorage API bool spendlist_is_active(); -zxerr_t spendlist_append_item(uint32_t p, uint64_t v, uint8_t *div, uint8_t *pkd, uint8_t *rcm, uint8_t *alpha); +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(); @@ -159,10 +160,11 @@ spend_item_t *spendlist_extract_next(); bool spendlist_more_extract(); -//outputlist flashstorage API +// outputlist flashstorage API bool outputlist_is_active(); -zxerr_t outputlist_append_item(uint8_t *d, uint8_t *pkd, uint64_t v, uint8_t memotype, uint8_t *ovk, uint8_t *rcmv, +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); uint8_t outputlist_len(); diff --git a/app/src/parser.c b/app/src/parser.c index 2e158927..98f20aee 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -1,422 +1,431 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ -#include -#include -#include -#include "app_mode.h" #include "parser.h" -#include "parser_impl.h" +#include "app_mode.h" #include "parser_common.h" +#include "parser_impl.h" +#include +#include +#include +#include "base58.h" +#include "bech32.h" #include "coin.h" +#include "nvdata.h" #include "parser_txdef.h" #include "rslib.h" -#include "nvdata.h" -#include "bech32.h" -#include "base58.h" #include "view.h" #include -#define DEFAULT_MEMOTYPE 0xf6 +#define DEFAULT_MEMOTYPE 0xf6 typedef enum { - type_tin = 0, - type_tout = 1, - type_sspend = 2, - type_sout = 3, - type_txfee = 4, + type_tin = 0, + type_tout = 1, + type_sspend = 2, + type_sout = 3, + type_txfee = 4, } sapling_parser_type_e; typedef struct { - sapling_parser_type_e type; - uint8_t index; + sapling_parser_type_e type; + uint8_t index; } parser_sapling_t; -parser_error_t parser_sapling_path_with_div(const uint8_t *data, size_t dataLen, parser_addr_div_t *prs) { - if (dataLen < 15) { - return parser_context_unexpected_size; - } - parser_context_t pars_ctx; - parser_error_t pars_err; - pars_ctx.offset = 0; - pars_ctx.buffer = data; - pars_ctx.bufferLen = 4; - uint32_t p = 0; - pars_err = _readUInt32(&pars_ctx, &p); - if (pars_err != parser_ok) { - return pars_err; - } - prs->path = p | 0x80000000; - memcpy(prs->div, data + 4, 11); - return parser_ok; +parser_error_t parser_sapling_path_with_div(const uint8_t *data, size_t dataLen, + parser_addr_div_t *prs) { + if (dataLen < 15) { + return parser_context_unexpected_size; + } + parser_context_t pars_ctx; + parser_error_t pars_err; + pars_ctx.offset = 0; + pars_ctx.buffer = data; + pars_ctx.bufferLen = 4; + uint32_t p = 0; + pars_err = _readUInt32(&pars_ctx, &p); + if (pars_err != parser_ok) { + return pars_err; + } + prs->path = p | 0x80000000; + memcpy(prs->div, data + 4, 11); + return parser_ok; } -parser_error_t parser_sapling_path(const uint8_t *data, size_t dataLen, uint32_t *p) { - if (dataLen < 4) { - return parser_context_unexpected_size; - } - parser_context_t pars_ctx; - parser_error_t pars_err; - pars_ctx.offset = 0; - pars_ctx.buffer = data; - pars_ctx.bufferLen = 4; - pars_err = _readUInt32(&pars_ctx, p); - if (pars_err != parser_ok) { - return pars_err; - } - *p |= 0x80000000; - return parser_ok; +parser_error_t parser_sapling_path(const uint8_t *data, size_t dataLen, + uint32_t *p) { + if (dataLen < 4) { + return parser_context_unexpected_size; + } + parser_context_t pars_ctx; + parser_error_t pars_err; + pars_ctx.offset = 0; + pars_ctx.buffer = data; + pars_ctx.bufferLen = 4; + pars_err = _readUInt32(&pars_ctx, p); + if (pars_err != parser_ok) { + return pars_err; + } + *p |= 0x80000000; + return parser_ok; } void view_tx_state() { - #if !defined(TARGET_STAX) - uint8_t state = get_state(); - switch (state) { - case STATE_PROCESSED_INPUTS: - case STATE_PROCESSED_SPEND_EXTRACTIONS: { - view_message_show("Zcash", "Step [1/5]"); - break; - } - - case STATE_PROCESSED_ALL_EXTRACTIONS: { - view_message_show("Zcash", "Step [2/5]"); - break; - } - - case STATE_CHECKING_ALL_TXDATA: { - view_message_show("Zcash", "Step [3/5]"); - break; - } - - case STATE_VERIFIED_ALL_TXDATA: { - view_message_show("Zcash", "Step [4/5]"); - break; - } - - case STATE_SIGNED_TX: { - view_message_show("Zcash", "Step [5/5]"); - break; - } - - default: { - view_idle_show(0, NULL); - } - } - UX_WAIT_DISPLAYED(); - #endif - return; +#if !defined(TARGET_STAX) + uint8_t state = get_state(); + switch (state) { + case STATE_PROCESSED_INPUTS: + case STATE_PROCESSED_SPEND_EXTRACTIONS: { + view_message_show("Zcash", "Step [1/5]"); + break; + } + + case STATE_PROCESSED_ALL_EXTRACTIONS: { + view_message_show("Zcash", "Step [2/5]"); + break; + } + + case STATE_CHECKING_ALL_TXDATA: { + view_message_show("Zcash", "Step [3/5]"); + break; + } + + case STATE_VERIFIED_ALL_TXDATA: { + view_message_show("Zcash", "Step [4/5]"); + break; + } + + case STATE_SIGNED_TX: { + view_message_show("Zcash", "Step [5/5]"); + break; + } + + default: { + view_idle_show(0, NULL); + } + } + UX_WAIT_DISPLAYED(); +#endif + return; } -parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t dataLen) { - CHECK_PARSER_ERR(parser_init(ctx, data, dataLen)) - +parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, + size_t dataLen) { + CHECK_PARSER_ERR(parser_init(ctx, data, dataLen)) - - return parser_ok; + return parser_ok; } parser_error_t parser_validate() { - // Iterate through all items to check that all can be shown and are valid - uint8_t numItems = 0; - CHECK_PARSER_ERR(parser_getNumItems(&numItems)) + // Iterate through all items to check that all can be shown and are valid + uint8_t numItems = 0; + CHECK_PARSER_ERR(parser_getNumItems(&numItems)) - char tmpKey[30]; - char tmpVal[30]; + char tmpKey[30]; + char tmpVal[30]; - for (uint8_t idx = 0; idx < numItems; idx++) { - uint8_t pageCount = 0; - CHECK_PARSER_ERR(parser_getItem( idx, tmpKey, sizeof(tmpKey), tmpVal, sizeof(tmpVal), 0, &pageCount)) - } + for (uint8_t idx = 0; idx < numItems; idx++) { + uint8_t pageCount = 0; + CHECK_PARSER_ERR(parser_getItem(idx, tmpKey, sizeof(tmpKey), tmpVal, + sizeof(tmpVal), 0, &pageCount)) + } - return parser_ok; + return parser_ok; } parser_error_t parser_sapling_display_value(uint64_t value, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) { - char tmpBuffer[100]; - fpuint64_to_str(tmpBuffer, sizeof(tmpBuffer), value, 8); - pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); - return parser_ok; + char tmpBuffer[100]; + fpuint64_to_str(tmpBuffer, sizeof(tmpBuffer), value, 8); + pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); + return parser_ok; } -parser_error_t parser_sapling_display_address_t(const uint8_t *addr, char *outVal, - uint16_t outValLen, uint8_t pageIdx, +parser_error_t parser_sapling_display_address_t(const uint8_t *addr, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, uint8_t *pageCount) { - MEMZERO(outVal, outValLen); + MEMZERO(outVal, outValLen); - uint8_t address[VERSION_SIZE + CX_RIPEMD160_SIZE + CX_SHA256_SIZE]; - address[0] = VERSION_P2PKH >> 8; - address[1] = VERSION_P2PKH & 0xFF; - MEMCPY(address + VERSION_SIZE, addr + 4, CX_RIPEMD160_SIZE); + uint8_t address[VERSION_SIZE + CX_RIPEMD160_SIZE + CX_SHA256_SIZE]; + address[0] = VERSION_P2PKH >> 8; + address[1] = VERSION_P2PKH & 0xFF; + MEMCPY(address + VERSION_SIZE, addr + 4, CX_RIPEMD160_SIZE); - cx_hash_sha256(address, - VERSION_SIZE + CX_RIPEMD160_SIZE, - address + VERSION_SIZE + CX_RIPEMD160_SIZE, - CX_SHA256_SIZE); + cx_hash_sha256(address, VERSION_SIZE + CX_RIPEMD160_SIZE, + address + VERSION_SIZE + CX_RIPEMD160_SIZE, CX_SHA256_SIZE); - cx_hash_sha256(address + VERSION_SIZE + CX_RIPEMD160_SIZE, CX_SHA256_SIZE, - address + VERSION_SIZE + CX_RIPEMD160_SIZE, CX_SHA256_SIZE); + cx_hash_sha256(address + VERSION_SIZE + CX_RIPEMD160_SIZE, CX_SHA256_SIZE, + address + VERSION_SIZE + CX_RIPEMD160_SIZE, CX_SHA256_SIZE); - uint8_t tmpBuffer[60]; - size_t outLen = sizeof(tmpBuffer); + uint8_t tmpBuffer[60]; + size_t outLen = sizeof(tmpBuffer); - int err = encode_base58(address, VERSION_SIZE + CX_RIPEMD160_SIZE + CHECKSUM_SIZE, tmpBuffer, &outLen); - if (err != 0) { - return parser_unexpected_error; - } + int err = + encode_base58(address, VERSION_SIZE + CX_RIPEMD160_SIZE + CHECKSUM_SIZE, + tmpBuffer, &outLen); + if (err != 0) { + return parser_unexpected_error; + } - pageString(outVal, outValLen, (char *) tmpBuffer, pageIdx, pageCount); - return parser_ok; + pageString(outVal, outValLen, (char *)tmpBuffer, pageIdx, pageCount); + return parser_ok; } -parser_error_t parser_sapling_display_address_s(uint8_t *div, uint8_t *pkd, char *outVal, - uint16_t outValLen, uint8_t pageIdx, +parser_error_t parser_sapling_display_address_s(uint8_t *div, uint8_t *pkd, + char *outVal, + uint16_t outValLen, + uint8_t pageIdx, uint8_t *pageCount) { - uint8_t address[DIV_SIZE + PKD_SIZE]; - MEMCPY(address, div, DIV_SIZE); - MEMCPY(address + DIV_SIZE, pkd, PKD_SIZE); - char tmpBuffer[100]; - bech32EncodeFromBytes(tmpBuffer, sizeof(tmpBuffer), - BECH32_HRP, - address, - sizeof(address), - 1, BECH32_ENCODING_BECH32); - pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); - return parser_ok; + uint8_t address[DIV_SIZE + PKD_SIZE]; + MEMCPY(address, div, DIV_SIZE); + MEMCPY(address + DIV_SIZE, pkd, PKD_SIZE); + char tmpBuffer[100]; + bech32EncodeFromBytes(tmpBuffer, sizeof(tmpBuffer), BECH32_HRP, address, + sizeof(address), 1, BECH32_ENCODING_BECH32); + pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); + return parser_ok; } -parser_error_t parser_sapling_getTypes(const uint16_t displayIdx, parser_sapling_t *prs) { - uint16_t index = displayIdx; +parser_error_t parser_sapling_getTypes(const uint16_t displayIdx, + parser_sapling_t *prs) { + uint16_t index = displayIdx; - if (index < t_inlist_len() * NUM_ITEMS_TIN && t_inlist_len() > 0) { - prs->type = type_tin; - prs->index = index; - return parser_ok; - } - index -= t_inlist_len() * NUM_ITEMS_TIN; - if (index < t_outlist_len() * NUM_ITEMS_TOUT && t_outlist_len() > 0) { - prs->type = type_tout; - prs->index = index; - return parser_ok; - } - index -= t_outlist_len() * NUM_ITEMS_TOUT; - if (index < spendlist_len() * NUM_ITEMS_SSPEND && spendlist_len() > 0) { - prs->type = type_sspend; - prs->index = index; - return parser_ok; - } - index -= spendlist_len() * NUM_ITEMS_SSPEND; - if (index < outputlist_len() * NUM_ITEMS_SOUT && outputlist_len() > 0) { - prs->type = type_sout; - prs->index = index; - return parser_ok; - } - prs->type = type_txfee; + if (index < t_inlist_len() * NUM_ITEMS_TIN && t_inlist_len() > 0) { + prs->type = type_tin; + prs->index = index; + return parser_ok; + } + index -= t_inlist_len() * NUM_ITEMS_TIN; + if (index < t_outlist_len() * NUM_ITEMS_TOUT && t_outlist_len() > 0) { + prs->type = type_tout; + prs->index = index; + return parser_ok; + } + index -= t_outlist_len() * NUM_ITEMS_TOUT; + if (index < spendlist_len() * NUM_ITEMS_SSPEND && spendlist_len() > 0) { + prs->type = type_sspend; + prs->index = index; + return parser_ok; + } + index -= spendlist_len() * NUM_ITEMS_SSPEND; + if (index < outputlist_len() * NUM_ITEMS_SOUT && outputlist_len() > 0) { + prs->type = type_sout; + prs->index = index; return parser_ok; + } + prs->type = type_txfee; + return parser_ok; } parser_error_t parser_getNumItems(uint8_t *num_items) { - *num_items = t_inlist_len() * NUM_ITEMS_TIN + - t_outlist_len() * NUM_ITEMS_TOUT + - spendlist_len() * NUM_ITEMS_SSPEND + - outputlist_len() * NUM_ITEMS_SOUT + - NUM_ITEMS_CONST; + *num_items = t_inlist_len() * NUM_ITEMS_TIN + + t_outlist_len() * NUM_ITEMS_TOUT + + spendlist_len() * NUM_ITEMS_SSPEND + + outputlist_len() * NUM_ITEMS_SOUT + NUM_ITEMS_CONST; - return parser_ok; + return parser_ok; } -parser_error_t parser_getItem(uint8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outVal, uint16_t outValLen, - uint8_t pageIdx, uint8_t *pageCount) { - MEMZERO(outKey, outKeyLen); - MEMZERO(outVal, outValLen); - snprintf(outKey, outKeyLen, "?"); - snprintf(outVal, outValLen, "?"); - *pageCount = 1; - - uint8_t numItems; - CHECK_PARSER_ERR(parser_getNumItems(&numItems)) - CHECK_APP_CANARY() - - - if (displayIdx < 0 || displayIdx >= numItems) { - return parser_no_data; +parser_error_t parser_getItem(uint8_t displayIdx, char *outKey, + uint16_t outKeyLen, char *outVal, + uint16_t outValLen, uint8_t pageIdx, + uint8_t *pageCount) { + MEMZERO(outKey, outKeyLen); + MEMZERO(outVal, outValLen); + snprintf(outKey, outKeyLen, "?"); + snprintf(outVal, outValLen, "?"); + *pageCount = 1; + + uint8_t numItems; + CHECK_PARSER_ERR(parser_getNumItems(&numItems)) + CHECK_APP_CANARY() + + if (displayIdx < 0 || displayIdx >= numItems) { + return parser_no_data; + } + + parser_sapling_t prs; + MEMZERO(&prs, sizeof(parser_sapling_t)); + CHECK_PARSER_ERR(parser_sapling_getTypes(displayIdx, &prs)); + + // FIXME: what decimals to take for ZECs? + + switch (prs.type) { + case type_tin: { + uint8_t itemnum = prs.index / NUM_ITEMS_TIN; + const t_input_item_t *item = t_inlist_retrieve_item(itemnum); + uint8_t itemtype = prs.index % NUM_ITEMS_TIN; + + switch (itemtype) { + case 0: { + snprintf(outKey, outKeyLen, "T-in addr"); + return parser_sapling_display_address_t(item->script, outVal, outValLen, + pageIdx, pageCount); + } + case 1: { + snprintf(outKey, outKeyLen, "T-in (ZEC)"); + return parser_sapling_display_value(item->value, outVal, outValLen, + pageIdx, pageCount); + } + } + } + + case type_tout: { + uint8_t itemnum = prs.index / NUM_ITEMS_TOUT; + t_output_item_t *item = t_outlist_retrieve_item(itemnum); + uint8_t itemtype = prs.index % NUM_ITEMS_TOUT; + switch (itemtype) { + case 0: { + snprintf(outKey, outKeyLen, "T-out addr"); + return parser_sapling_display_address_t(item->address, outVal, outValLen, + pageIdx, pageCount); + } + case 1: { + snprintf(outKey, outKeyLen, "T-out (ZEC)"); + return parser_sapling_display_value(item->value, outVal, outValLen, + pageIdx, pageCount); + } + } + } + case type_sspend: { + uint8_t itemnum = prs.index / NUM_ITEMS_SSPEND; + spend_item_t *item = spendlist_retrieve_item(itemnum); + uint8_t itemtype = prs.index % NUM_ITEMS_SSPEND; + switch (itemtype) { + case 0: { + snprintf(outKey, outKeyLen, "S-in addr"); + return parser_sapling_display_address_s(item->div, item->pkd, outVal, + outValLen, pageIdx, pageCount); + } + case 1: { + snprintf(outKey, outKeyLen, "S-in (ZEC)"); + return parser_sapling_display_value(item->value, outVal, outValLen, + pageIdx, pageCount); + } + } + } + + case type_sout: { + + uint8_t itemnum = prs.index / NUM_ITEMS_SOUT; + output_item_t *item = outputlist_retrieve_item(itemnum); + uint8_t itemtype = prs.index % NUM_ITEMS_SOUT; + switch (itemtype) { + case 0: { + snprintf(outKey, outKeyLen, "S-out addr"); + return parser_sapling_display_address_s(item->div, item->pkd, outVal, + outValLen, pageIdx, pageCount); + } + case 1: { + snprintf(outKey, outKeyLen, "S-out (ZEC)"); + return parser_sapling_display_value(item->value, outVal, outValLen, + pageIdx, pageCount); + } + case 2: { + snprintf(outKey, outKeyLen, "S-out Memotype"); + if (item->memotype == DEFAULT_MEMOTYPE) { + snprintf(outVal, outValLen, "Default"); + } else { + snprintf(outVal, outValLen, "Custom"); + } + return parser_ok; } - parser_sapling_t prs; - MEMZERO(&prs, sizeof(parser_sapling_t)); - CHECK_PARSER_ERR(parser_sapling_getTypes(displayIdx, &prs)); - - // FIXME: what decimals to take for ZECs? - - switch (prs.type) { - case type_tin : { - uint8_t itemnum = prs.index / NUM_ITEMS_TIN; - const t_input_item_t *item = t_inlist_retrieve_item(itemnum); - uint8_t itemtype = prs.index % NUM_ITEMS_TIN; - - switch (itemtype) { - case 0: { - snprintf(outKey, outKeyLen, "T-in addr"); - return parser_sapling_display_address_t(item->script, outVal, outValLen, pageIdx, pageCount); - } - case 1: { - snprintf(outKey, outKeyLen, "T-in (ZEC)"); - return parser_sapling_display_value(item->value, outVal, outValLen, pageIdx, pageCount); - } - } - } - - case type_tout : { - uint8_t itemnum = prs.index / NUM_ITEMS_TOUT; - t_output_item_t *item = t_outlist_retrieve_item(itemnum); - uint8_t itemtype = prs.index % NUM_ITEMS_TOUT; - switch (itemtype) { - case 0: { - snprintf(outKey, outKeyLen, "T-out addr"); - return parser_sapling_display_address_t(item->address, outVal, outValLen, pageIdx, pageCount); - } - case 1: { - snprintf(outKey, outKeyLen, "T-out (ZEC)"); - return parser_sapling_display_value(item->value, outVal, outValLen, pageIdx, pageCount); - } - } - } - case type_sspend: { - uint8_t itemnum = prs.index / NUM_ITEMS_SSPEND; - spend_item_t *item = spendlist_retrieve_item(itemnum); - uint8_t itemtype = prs.index % NUM_ITEMS_SSPEND; - switch (itemtype) { - case 0: { - snprintf(outKey, outKeyLen, "S-in addr"); - return parser_sapling_display_address_s(item->div, item->pkd, outVal, outValLen, pageIdx, - pageCount); - } - case 1: { - snprintf(outKey, outKeyLen, "S-in (ZEC)"); - return parser_sapling_display_value(item->value, outVal, outValLen, pageIdx, pageCount); - } - } - } - - case type_sout: { - - uint8_t itemnum = prs.index / NUM_ITEMS_SOUT; - output_item_t *item = outputlist_retrieve_item(itemnum); - uint8_t itemtype = prs.index % NUM_ITEMS_SOUT; - switch (itemtype) { - case 0: { - snprintf(outKey, outKeyLen, "S-out addr"); - return parser_sapling_display_address_s(item->div, item->pkd, outVal, outValLen, pageIdx, - pageCount); - } - case 1: { - snprintf(outKey, outKeyLen, "S-out (ZEC)"); - return parser_sapling_display_value(item->value, outVal, outValLen, pageIdx, pageCount); - } - case 2: { - snprintf(outKey, outKeyLen, "S-out Memotype"); - if (item->memotype == DEFAULT_MEMOTYPE) { - snprintf(outVal, outValLen, "Default"); - } else { - snprintf(outVal, outValLen, "Custom"); - } - return parser_ok; - } - - case 3: { - snprintf(outKey, outKeyLen, "S-out OVK"); - uint8_t dummy[OVK_SIZE]; - MEMZERO(dummy, sizeof(dummy)); - if (item->ovk[0] == 0x01) { - char tmpBuffer[100]; - array_to_hexstr(tmpBuffer, sizeof(tmpBuffer), item->ovk + 1, OVK_SIZE); - pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); - return parser_ok; - } else { - snprintf(outVal, outValLen, "None"); - } - return parser_ok; - } - } - } - - case type_txfee: { - snprintf(outKey, outKeyLen, "Fee"); - return parser_sapling_display_value(get_totalvalue(), outVal, outValLen, pageIdx, pageCount); - } - - default: { - return parser_no_data; - } + case 3: { + snprintf(outKey, outKeyLen, "S-out OVK"); + uint8_t dummy[OVK_SIZE]; + MEMZERO(dummy, sizeof(dummy)); + if (item->ovk[0] == 0x01) { + char tmpBuffer[100]; + array_to_hexstr(tmpBuffer, sizeof(tmpBuffer), item->ovk + 1, OVK_SIZE); + pageString(outVal, outValLen, tmpBuffer, pageIdx, pageCount); + return parser_ok; + } else { + snprintf(outVal, outValLen, "None"); + } + return parser_ok; } - return parser_ok; + } + } + + case type_txfee: { + snprintf(outKey, outKeyLen, "Fee"); + return parser_sapling_display_value(get_totalvalue(), outVal, outValLen, + pageIdx, pageCount); + } + + default: { + return parser_no_data; + } + } + return parser_ok; } const char *parser_getErrorDescription(parser_error_t err) { - switch (err) { - // General errors - case parser_ok: - return "No error"; - case parser_no_data: - return "No more data"; - case parser_init_context_empty: - return "Initialized empty context"; - case parser_display_idx_out_of_range: - return "display_idx_out_of_range"; - case parser_display_page_out_of_range: - return "display_page_out_of_range"; - case parser_unexpected_error: - return "Unexpected internal error"; - case parser_no_memory_for_state: - return "No enough memory for parser state"; - /////////// Context specific - case parser_context_mismatch: - return "context prefix is invalid"; - case parser_context_unexpected_size: - return "context unexpected size"; - case parser_context_invalid_chars: - return "context invalid chars"; - // Required fields error - // Coin specific - case parser_invalid_output_script: - return "Invalid output script"; - case parser_unexpected_type: - return "Unexpected data type"; - case parser_unexpected_method: - return "Unexpected method"; - case parser_unexpected_buffer_end: - return "Unexpected buffer end"; - case parser_unexpected_value: - return "Unexpected value"; - case parser_unexpected_number_items: - return "Unexpected number of items"; - case parser_unexpected_characters: - return "Unexpected characters"; - case parser_unexpected_field: - return "Unexpected field"; - case parser_value_out_of_range: - return "Value out of range"; - case parser_invalid_address: - return "Invalid address format"; - default: - return "Unrecognized error code"; - } + switch (err) { + // General errors + case parser_ok: + return "No error"; + case parser_no_data: + return "No more data"; + case parser_init_context_empty: + return "Initialized empty context"; + case parser_display_idx_out_of_range: + return "display_idx_out_of_range"; + case parser_display_page_out_of_range: + return "display_page_out_of_range"; + case parser_unexpected_error: + return "Unexpected internal error"; + case parser_no_memory_for_state: + return "No enough memory for parser state"; + /////////// Context specific + case parser_context_mismatch: + return "context prefix is invalid"; + case parser_context_unexpected_size: + return "context unexpected size"; + case parser_context_invalid_chars: + return "context invalid chars"; + // Required fields error + // Coin specific + case parser_invalid_output_script: + return "Invalid output script"; + case parser_unexpected_type: + return "Unexpected data type"; + case parser_unexpected_method: + return "Unexpected method"; + case parser_unexpected_buffer_end: + return "Unexpected buffer end"; + case parser_unexpected_value: + return "Unexpected value"; + case parser_unexpected_number_items: + return "Unexpected number of items"; + case parser_unexpected_characters: + return "Unexpected characters"; + case parser_unexpected_field: + return "Unexpected field"; + case parser_value_out_of_range: + return "Value out of range"; + case parser_invalid_address: + return "Invalid address format"; + default: + return "Unrecognized error code"; + } } diff --git a/app/src/parser.h b/app/src/parser.h index ace10ccd..0814d290 100644 --- a/app/src/parser.h +++ b/app/src/parser.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -20,31 +20,34 @@ extern "C" { #endif +#include "crypto.h" +#include "hexutils.h" #include "parser_common.h" #include "parser_txdef.h" -#include "hexutils.h" -#include "crypto.h" -#define NUM_ITEMS_TIN 2 //address, value -#define NUM_ITEMS_TOUT 2 //address, value -#define NUM_ITEMS_SSPEND 2 //address, value -#define NUM_ITEMS_SOUT 4 //address, value, memotype, OVK? -#define NUM_ITEMS_CONST 1 //txfee +#define NUM_ITEMS_TIN 2 // address, value +#define NUM_ITEMS_TOUT 2 // address, value +#define NUM_ITEMS_SSPEND 2 // address, value +#define NUM_ITEMS_SOUT 4 // address, value, memotype, OVK? +#define NUM_ITEMS_CONST 1 // txfee typedef struct { - uint32_t path; - uint8_t div[11]; + uint32_t path; + uint8_t div[11]; } parser_addr_div_t; -parser_error_t parser_sapling_path_with_div(const uint8_t *data, size_t dataLen, parser_addr_div_t *prs); -parser_error_t parser_sapling_path(const uint8_t *data, size_t dataLen, uint32_t *p); +parser_error_t parser_sapling_path_with_div(const uint8_t *data, size_t dataLen, + parser_addr_div_t *prs); +parser_error_t parser_sapling_path(const uint8_t *data, size_t dataLen, + uint32_t *p); void view_tx_state(); 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); +parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, + size_t dataLen); //// verifies tx fields parser_error_t parser_validate(); @@ -53,10 +56,10 @@ parser_error_t parser_validate(); parser_error_t parser_getNumItems(uint8_t *num_items); // retrieves a readable output for each field / page -parser_error_t parser_getItem(uint8_t displayIdx, - char *outKey, uint16_t outKeyLen, - char *outValue, uint16_t outValueLen, - uint8_t pageIdx, uint8_t *pageCount); +parser_error_t parser_getItem(uint8_t displayIdx, char *outKey, + uint16_t outKeyLen, char *outValue, + uint16_t outValueLen, uint8_t pageIdx, + uint8_t *pageCount); void parser_resetState(); diff --git a/app/src/parser_common.h b/app/src/parser_common.h index 0c4b836f..c750abcf 100644 --- a/app/src/parser_common.h +++ b/app/src/parser_common.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2019 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #ifdef __cplusplus @@ -20,58 +20,61 @@ extern "C" { #endif #include "parser_txdef.h" -#include #include +#include -#define CHECK_PARSER_ERR(__CALL) { \ - parser_error_t __err = __CALL; \ - CHECK_APP_CANARY() \ - if (__err!=parser_ok) return __err;} +#define CHECK_PARSER_ERR(__CALL) \ + { \ + parser_error_t __err = __CALL; \ + CHECK_APP_CANARY() \ + if (__err != parser_ok) \ + return __err; \ + } typedef enum { - // Generic errors - parser_ok = 0, - parser_no_data, - parser_init_context_empty, - parser_display_idx_out_of_range, - parser_display_page_out_of_range, - parser_unexpected_error, - parser_no_memory_for_state, - // Context related errors - parser_context_mismatch, - parser_context_unexpected_size, - parser_context_invalid_chars, - parser_context_unknown_prefix, - // Required fields - //////////////////////// - // Coin specific - parser_invalid_output_script, - parser_unexpected_type, - parser_unexpected_method, - parser_not_allowed, - parser_not_supported, - parser_unexpected_buffer_end, - parser_unexpected_value, - parser_unexpected_number_items, - parser_unexpected_characters, - parser_unexpected_field, - parser_value_out_of_range, - parser_invalid_address, - parser_value_too_many_bytes, - parser_unexpected_module, - parser_unexpected_callIndex, - parser_unexpected_unparsed_bytes, - parser_print_not_supported, - parser_tx_nesting_not_supported, - parser_tx_nesting_limit_reached, - parser_tx_call_vec_too_large, + // Generic errors + parser_ok = 0, + parser_no_data, + parser_init_context_empty, + parser_display_idx_out_of_range, + parser_display_page_out_of_range, + parser_unexpected_error, + parser_no_memory_for_state, + // Context related errors + parser_context_mismatch, + parser_context_unexpected_size, + parser_context_invalid_chars, + parser_context_unknown_prefix, + // Required fields + //////////////////////// + // Coin specific + parser_invalid_output_script, + parser_unexpected_type, + parser_unexpected_method, + parser_not_allowed, + parser_not_supported, + parser_unexpected_buffer_end, + parser_unexpected_value, + parser_unexpected_number_items, + parser_unexpected_characters, + parser_unexpected_field, + parser_value_out_of_range, + parser_invalid_address, + parser_value_too_many_bytes, + parser_unexpected_module, + parser_unexpected_callIndex, + parser_unexpected_unparsed_bytes, + parser_print_not_supported, + parser_tx_nesting_not_supported, + parser_tx_nesting_limit_reached, + parser_tx_call_vec_too_large, } parser_error_t; typedef struct { - const uint8_t *buffer; - uint16_t bufferLen; - uint16_t offset; - parser_tx_t *tx_obj; + const uint8_t *buffer; + uint16_t bufferLen; + uint16_t offset; + parser_tx_t *tx_obj; } parser_context_t; #ifdef __cplusplus diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 9eeb7472..4a010155 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -1,92 +1,94 @@ /******************************************************************************* -* (c) 2019 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ -#include #include "parser_impl.h" -#include "parser_txdef.h" #include "coin.h" #include "crypto.h" +#include "parser_txdef.h" #include "zxformat.h" +#include -parser_error_t parser_init_context(parser_context_t *ctx, const uint8_t *buffer, uint16_t bufferSize) { - ctx->offset = 0; - ctx->buffer = NULL; - ctx->bufferLen = 0; +parser_error_t parser_init_context(parser_context_t *ctx, const uint8_t *buffer, + uint16_t bufferSize) { + ctx->offset = 0; + ctx->buffer = NULL; + ctx->bufferLen = 0; - if (bufferSize == 0 || buffer == NULL) { - // Not available, use defaults - return parser_init_context_empty; - } + if (bufferSize == 0 || buffer == NULL) { + // Not available, use defaults + return parser_init_context_empty; + } - ctx->buffer = buffer; - ctx->bufferLen = bufferSize; + ctx->buffer = buffer; + ctx->bufferLen = bufferSize; - ZEMU_LOGF(100, "init_context %d bytes", bufferSize); + ZEMU_LOGF(100, "init_context %d bytes", bufferSize); - return parser_ok; + return parser_ok; } -parser_error_t parser_init(parser_context_t *ctx, const uint8_t *buffer, uint16_t bufferSize) { - CHECK_PARSER_ERR(parser_init_context(ctx, buffer, bufferSize)) - return parser_ok; +parser_error_t parser_init(parser_context_t *ctx, const uint8_t *buffer, + uint16_t bufferSize) { + CHECK_PARSER_ERR(parser_init_context(ctx, buffer, bufferSize)) + return parser_ok; } const char *parser_getErrorDescription(parser_error_t err) { - switch (err) { - // General errors - case parser_ok: - return "No error"; - case parser_no_data: - return "No more data"; - case parser_init_context_empty: - return "Initialized empty context"; - case parser_display_idx_out_of_range: - return "display_idx_out_of_range"; - case parser_display_page_out_of_range: - return "display_page_out_of_range"; - // Coin specific - case parser_not_allowed: - return "Not allowed"; - case parser_not_supported: - return "Not supported"; - case parser_unexpected_buffer_end: - return "Unexpected buffer end"; - case parser_unexpected_value: - return "Unexpected value"; - case parser_value_out_of_range: - return "Value out of range"; - case parser_value_too_many_bytes: - return "Value too many bytes"; - case parser_unexpected_module: - return "Unexpected module"; - case parser_unexpected_callIndex: - return "Unexpected call index"; - case parser_unexpected_unparsed_bytes: - return "Unexpected unparsed bytes"; - case parser_print_not_supported: - return "Value cannot be printed"; - case parser_tx_nesting_not_supported: - return "Call nesting not supported"; - case parser_tx_nesting_limit_reached: - return "Max nested calls reached"; - case parser_tx_call_vec_too_large: - return "Call vector exceeds limit"; - default: - return "Unrecognized error code"; - } + switch (err) { + // General errors + case parser_ok: + return "No error"; + case parser_no_data: + return "No more data"; + case parser_init_context_empty: + return "Initialized empty context"; + case parser_display_idx_out_of_range: + return "display_idx_out_of_range"; + case parser_display_page_out_of_range: + return "display_page_out_of_range"; + // Coin specific + case parser_not_allowed: + return "Not allowed"; + case parser_not_supported: + return "Not supported"; + case parser_unexpected_buffer_end: + return "Unexpected buffer end"; + case parser_unexpected_value: + return "Unexpected value"; + case parser_value_out_of_range: + return "Value out of range"; + case parser_value_too_many_bytes: + return "Value too many bytes"; + case parser_unexpected_module: + return "Unexpected module"; + case parser_unexpected_callIndex: + return "Unexpected call index"; + case parser_unexpected_unparsed_bytes: + return "Unexpected unparsed bytes"; + case parser_print_not_supported: + return "Value cannot be printed"; + case parser_tx_nesting_not_supported: + return "Call nesting not supported"; + case parser_tx_nesting_limit_reached: + return "Max nested calls reached"; + case parser_tx_call_vec_too_large: + return "Call vector exceeds limit"; + default: + return "Unrecognized error code"; + } } GEN_DEF_READFIX_UNSIGNED(8) diff --git a/app/src/parser_impl.h b/app/src/parser_impl.h index 5b01153b..e19339d9 100644 --- a/app/src/parser_impl.h +++ b/app/src/parser_impl.h @@ -1,94 +1,111 @@ /******************************************************************************* -* (c) 2019 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #include "parser_common.h" #include "parser_txdef.h" -#include #include "zxtypes.h" +#include #ifdef __cplusplus extern "C" { #endif -#include #include +#include #include - // Checks that there are at least SIZE bytes available in the buffer -#define CTX_CHECK_AVAIL(CTX, SIZE) \ - if ( (CTX) == NULL || ((CTX)->offset + SIZE) > (CTX)->bufferLen) { return parser_unexpected_buffer_end; } +#define CTX_CHECK_AVAIL(CTX, SIZE) \ + if ((CTX) == NULL || ((CTX)->offset + SIZE) > (CTX)->bufferLen) { \ + return parser_unexpected_buffer_end; \ + } -#define CTX_CHECK_AND_ADVANCE(CTX, SIZE) \ - CTX_CHECK_AVAIL((CTX), (SIZE)) \ - (CTX)->offset += (SIZE); +#define CTX_CHECK_AND_ADVANCE(CTX, SIZE) \ + CTX_CHECK_AVAIL((CTX), (SIZE)) \ + (CTX)->offset += (SIZE); // Checks function input is valid -#define CHECK_INPUT() \ - if (v == NULL) { return parser_no_data; } \ - CTX_CHECK_AVAIL(c, 1) // Checks that there is something available in the buffer - -#define CLEAN_AND_CHECK() \ - MEMZERO(outValue, outValueLen); \ - if (v == NULL) { *pageCount = 0; return parser_no_data; } - -#define GEN_DEF_READARRAY(SIZE) \ - v->_ptr = c->buffer + c->offset; \ - CTX_CHECK_AND_ADVANCE(c, SIZE) \ - return parser_ok; - -#define GEN_DEF_TOSTRING_ARRAY(SIZE) \ - CLEAN_AND_CHECK(); \ - if (v->_ptr == NULL || outValueLen == 0 ) return parser_unexpected_buffer_end; \ - const uint16_t outLenNormalized = (outValueLen - 1) / 2; \ - *pageCount = SIZE / outLenNormalized; \ - if (SIZE % outLenNormalized != 0) *pageCount+=1; \ - const uint16_t pageOffset = pageIdx * outLenNormalized; \ - uint16_t loopmax = outLenNormalized; \ - if (loopmax > SIZE - pageOffset) loopmax = SIZE - pageOffset; \ - for (uint16_t i = 0; i < loopmax; i++) { \ - const uint16_t offset = i << 1u; \ - const uint8_t *c = v->_ptr + pageOffset; \ - snprintf(outValue + offset, outValueLen - offset, "%02x", c[i]); \ - } \ - return parser_ok; - -#define GEN_DEC_READFIX_UNSIGNED(BITS) parser_error_t _readUInt ## BITS(parser_context_t *ctx, uint ## BITS ##_t *value) -#define GEN_DEF_READFIX_UNSIGNED(BITS) parser_error_t _readUInt ## BITS(parser_context_t *ctx, uint ## BITS ##_t *value) \ -{ \ - if (value == NULL) return parser_no_data; \ - *value = 0u; \ - for(uint8_t i=0u; i < (BITS##u>>3u); i++, ctx->offset++) { \ - if (ctx->offset >= ctx->bufferLen) return parser_unexpected_buffer_end; \ - *value += (uint ## BITS ##_t) *(ctx->buffer + ctx->offset) << (8u*i); \ - } \ - return parser_ok; \ -} -#define GEN_DEC_READFIX_SIGNED(BITS) parser_error_t _readInt ## BITS(parser_context_t *ctx, int ## BITS ##_t *value) -#define GEN_DEF_READFIX_SIGNED(BITS) parser_error_t _readInt ## BITS(parser_context_t *ctx, int ## BITS ##_t *value) \ -{ \ - if (value == NULL) return parser_no_data; \ - *value = 0; \ - for(int8_t i=0; i < (BITS>>3); i++, ctx->offset++) { \ - if (ctx->offset >= ctx->bufferLen) return parser_unexpected_buffer_end; \ - *value += (int ## BITS ##_t) *(ctx->buffer + ctx->offset) << (8*i); \ - } \ - return parser_ok; \ -} +#define CHECK_INPUT() \ + if (v == NULL) { \ + return parser_no_data; \ + } \ + CTX_CHECK_AVAIL(c, \ + 1) // Checks that there is something available in the buffer + +#define CLEAN_AND_CHECK() \ + MEMZERO(outValue, outValueLen); \ + if (v == NULL) { \ + *pageCount = 0; \ + return parser_no_data; \ + } + +#define GEN_DEF_READARRAY(SIZE) \ + v->_ptr = c->buffer + c->offset; \ + CTX_CHECK_AND_ADVANCE(c, SIZE) \ + return parser_ok; + +#define GEN_DEF_TOSTRING_ARRAY(SIZE) \ + CLEAN_AND_CHECK(); \ + if (v->_ptr == NULL || outValueLen == 0) \ + return parser_unexpected_buffer_end; \ + const uint16_t outLenNormalized = (outValueLen - 1) / 2; \ + *pageCount = SIZE / outLenNormalized; \ + if (SIZE % outLenNormalized != 0) \ + *pageCount += 1; \ + const uint16_t pageOffset = pageIdx * outLenNormalized; \ + uint16_t loopmax = outLenNormalized; \ + if (loopmax > SIZE - pageOffset) \ + loopmax = SIZE - pageOffset; \ + for (uint16_t i = 0; i < loopmax; i++) { \ + const uint16_t offset = i << 1u; \ + const uint8_t *c = v->_ptr + pageOffset; \ + snprintf(outValue + offset, outValueLen - offset, "%02x", c[i]); \ + } \ + return parser_ok; + +#define GEN_DEC_READFIX_UNSIGNED(BITS) \ + parser_error_t _readUInt##BITS(parser_context_t *ctx, uint##BITS##_t *value) +#define GEN_DEF_READFIX_UNSIGNED(BITS) \ + parser_error_t _readUInt##BITS(parser_context_t *ctx, \ + uint##BITS##_t *value) { \ + if (value == NULL) \ + return parser_no_data; \ + *value = 0u; \ + for (uint8_t i = 0u; i < (BITS##u >> 3u); i++, ctx->offset++) { \ + if (ctx->offset >= ctx->bufferLen) \ + return parser_unexpected_buffer_end; \ + *value += (uint##BITS##_t) * (ctx->buffer + ctx->offset) << (8u * i); \ + } \ + return parser_ok; \ + } +#define GEN_DEC_READFIX_SIGNED(BITS) \ + parser_error_t _readInt##BITS(parser_context_t *ctx, int##BITS##_t *value) +#define GEN_DEF_READFIX_SIGNED(BITS) \ + parser_error_t _readInt##BITS(parser_context_t *ctx, int##BITS##_t *value) { \ + if (value == NULL) \ + return parser_no_data; \ + *value = 0; \ + for (int8_t i = 0; i < (BITS >> 3); i++, ctx->offset++) { \ + if (ctx->offset >= ctx->bufferLen) \ + return parser_unexpected_buffer_end; \ + *value += (int##BITS##_t) * (ctx->buffer + ctx->offset) << (8 * i); \ + } \ + return parser_ok; \ + } GEN_DEC_READFIX_UNSIGNED(8); @@ -100,8 +117,8 @@ GEN_DEC_READFIX_UNSIGNED(64); GEN_DEC_READFIX_SIGNED(64); -parser_error_t parser_init(parser_context_t *ctx, const uint8_t *buffer, uint16_t bufferSize); - +parser_error_t parser_init(parser_context_t *ctx, const uint8_t *buffer, + uint16_t bufferSize); #ifdef __cplusplus } diff --git a/app/src/parser_txdef.h b/app/src/parser_txdef.h index b19518b0..f5cce9cc 100644 --- a/app/src/parser_txdef.h +++ b/app/src/parser_txdef.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2019 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2019 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #include @@ -22,12 +22,12 @@ extern "C" { #endif -#include #include +#include typedef struct { - uint8_t *state; - uint16_t len; + uint8_t *state; + uint16_t len; } parser_tx_t; #ifdef __cplusplus diff --git a/app/src/sighash.c b/app/src/sighash.c index be2f6b9c..7dfb9336 100644 --- a/app/src/sighash.c +++ b/app/src/sighash.c @@ -1,191 +1,211 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ -#include -#include -#include -#include "os.h" -#include "cx.h" -#include "nvdata.h" #include "sighash.h" +#include "cx.h" #include "index_sapling.h" +#include "nvdata.h" +#include "os.h" #include "txid.h" +#include +#include +#include -#define ZCASH_PREVOUTS_HASH_PERSONALIZATION "ZcashPrevoutHash" -#define ZCASH_SEQUENCE_HASH_PERSONALIZATION "ZcashSequencHash" -#define ZCASH_OUTPUTS_HASH_PERSONALIZATION "ZcashOutputsHash" -//#define ZCASH_JOINSPLITS_HASH_PERSONALIZATION "ZcashJSplitsHash" not supported +#define ZCASH_PREVOUTS_HASH_PERSONALIZATION "ZcashPrevoutHash" +#define ZCASH_SEQUENCE_HASH_PERSONALIZATION "ZcashSequencHash" +#define ZCASH_OUTPUTS_HASH_PERSONALIZATION "ZcashOutputsHash" +// #define ZCASH_JOINSPLITS_HASH_PERSONALIZATION "ZcashJSplitsHash" not +// supported #define CTX_ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION "ZcashSSpendsHash" #define CTX_ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION "ZcashSOutputHash" -//const uint8_t CONSENSUS_BRANCH_ID_SAPLING[4] = {0x76, 0xb8, 0x09, 0xBB}; // sapling -//const uint8_t CONSENSUS_BRANCH_ID_ORCHARD[4] = {0xC2, 0xD6, 0xD0, 0xB4}; // orchard +// const uint8_t CONSENSUS_BRANCH_ID_SAPLING[4] = {0x76, 0xb8, 0x09, 0xBB}; // +// sapling const uint8_t CONSENSUS_BRANCH_ID_ORCHARD[4] = {0xC2, 0xD6, 0xD0, +// 0xB4}; // orchard // -const uint8_t CONSENSUS_BRANCH_ID_SAPLING[4] = {0xBB, 0x09, 0xB8, 0x76}; // sapling -const uint8_t CONSENSUS_BRANCH_ID_ORCHARD[4] = {0xB4, 0xD0, 0xD6, 0xC2}; // orchard +const uint8_t CONSENSUS_BRANCH_ID_SAPLING[4] = {0xBB, 0x09, 0xB8, + 0x76}; // sapling +const uint8_t CONSENSUS_BRANCH_ID_ORCHARD[4] = {0xB4, 0xD0, 0xD6, + 0xC2}; // orchard void sapling_transparent_prevouts_hash(const uint8_t *input, uint8_t *output) { - const uint8_t n = t_inlist_len(); - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) ZCASH_PREVOUTS_HASH_PERSONALIZATION, 16); - - if (n == 0) { - cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); - return; - } - - const uint8_t *data = input + INDEX_TIN_PREVOUT; - for (uint8_t i = 0; i < n - 1; i++, data += T_IN_TX_LEN) { - cx_hash_no_throw(&ctx.header, 0, data, 36, NULL, 0); - } - cx_hash_no_throw(&ctx.header, CX_LAST, data, 36, output, HASH_SIZE); + const uint8_t n = t_inlist_len(); + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, + (uint8_t *)ZCASH_PREVOUTS_HASH_PERSONALIZATION, 16); + + if (n == 0) { + cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); + return; + } + + const uint8_t *data = input + INDEX_TIN_PREVOUT; + for (uint8_t i = 0; i < n - 1; i++, data += T_IN_TX_LEN) { + cx_hash_no_throw(&ctx.header, 0, data, 36, NULL, 0); + } + cx_hash_no_throw(&ctx.header, CX_LAST, data, 36, output, HASH_SIZE); } void sapling_transparent_sequence_hash(const uint8_t *input, uint8_t *output) { - const uint8_t n = t_inlist_len(); + const uint8_t n = t_inlist_len(); + + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, + (uint8_t *)ZCASH_SEQUENCE_HASH_PERSONALIZATION, 16); + + if (n == 0) { + cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); + return; + } + + const uint8_t *data = input + INDEX_TIN_SEQ; + for (uint8_t i = 0; i < n - 1; i++, data += T_IN_TX_LEN) { + cx_hash_no_throw(&ctx.header, 0, data, 4, NULL, 0); + } + cx_hash_no_throw(&ctx.header, CX_LAST, data, 4, output, HASH_SIZE); +} - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) ZCASH_SEQUENCE_HASH_PERSONALIZATION, 16); +void v4_transparent_outputs_hash(uint8_t *output) { + const uint8_t n = t_outlist_len(); - if (n == 0) { - cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); - return; - } + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, + (uint8_t *)ZCASH_OUTPUTS_HASH_PERSONALIZATION, 16); - const uint8_t *data = input + INDEX_TIN_SEQ; - for (uint8_t i = 0; i < n - 1; i++, data += T_IN_TX_LEN) { - cx_hash_no_throw(&ctx.header, 0, data, 4, NULL, 0); - } - cx_hash_no_throw(&ctx.header, CX_LAST, data, 4, output, HASH_SIZE); -} + if (n == 0) { + cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); + return; + } -void v4_transparent_outputs_hash(uint8_t *output) { - const uint8_t n = t_outlist_len(); - - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) ZCASH_OUTPUTS_HASH_PERSONALIZATION, 16); - - if (n == 0) { - cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); - return; - } - - uint8_t data[34]; - uint8_t i = 0; - for (; i < n - 1; i++) { - t_output_item_t *item = t_outlist_retrieve_item(i); - MEMCPY(data, (uint8_t * ) & (item->value), 8); - MEMCPY(data + 8, item->address, SCRIPT_SIZE); - cx_hash_no_throw(&ctx.header, 0, data, sizeof(data), NULL, 0); - } + uint8_t data[34]; + uint8_t i = 0; + for (; i < n - 1; i++) { t_output_item_t *item = t_outlist_retrieve_item(i); - MEMCPY(data, (uint8_t * ) & (item->value), 8); + MEMCPY(data, (uint8_t *)&(item->value), 8); MEMCPY(data + 8, item->address, SCRIPT_SIZE); - cx_hash_no_throw(&ctx.header, CX_LAST, data, sizeof(data), output, HASH_SIZE); + cx_hash_no_throw(&ctx.header, 0, data, sizeof(data), NULL, 0); + } + t_output_item_t *item = t_outlist_retrieve_item(i); + MEMCPY(data, (uint8_t *)&(item->value), 8); + MEMCPY(data + 8, item->address, SCRIPT_SIZE); + cx_hash_no_throw(&ctx.header, CX_LAST, data, sizeof(data), output, HASH_SIZE); } - -void shielded_output_hash(const uint8_t *input, uint16_t inputlen, uint8_t *output) { - if (inputlen == 0) { - MEMZERO(output, HASH_SIZE); - return; - } - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) CTX_ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION, 16); - cx_hash_no_throw(&ctx.header, CX_LAST, input, inputlen, output, HASH_SIZE); +void shielded_output_hash(const uint8_t *input, uint16_t inputlen, + uint8_t *output) { + if (inputlen == 0) { + MEMZERO(output, HASH_SIZE); + return; + } + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw( + &ctx, 256, NULL, 0, + (uint8_t *)CTX_ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION, 16); + cx_hash_no_throw(&ctx.header, CX_LAST, input, inputlen, output, HASH_SIZE); } -void shielded_spend_hash(const uint8_t *input, uint16_t inputlen, uint8_t *output) { - if (inputlen == 0) { - MEMZERO(output, HASH_SIZE); - return; - } - cx_blake2b_t ctx; - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) CTX_ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION, 16); - cx_hash_no_throw(&ctx.header, CX_LAST, input, inputlen, output, HASH_SIZE); +void shielded_spend_hash(const uint8_t *input, uint16_t inputlen, + uint8_t *output) { + if (inputlen == 0) { + MEMZERO(output, HASH_SIZE); + return; + } + cx_blake2b_t ctx; + cx_blake2b_init2_no_throw( + &ctx, 256, NULL, 0, + (uint8_t *)CTX_ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION, 16); + cx_hash_no_throw(&ctx.header, CX_LAST, input, inputlen, output, HASH_SIZE); } -static void signature_hash_v4(const uint8_t *input, uint16_t inputlen, uint8_t *output) { - zemu_log_stack("signature_hash_v4"); - cx_blake2b_t ctx; +static void signature_hash_v4(const uint8_t *input, uint16_t inputlen, + uint8_t *output) { + zemu_log_stack("signature_hash_v4"); + cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, "ZcashSigHash", 12); - MEMCPY(personalization + 12, CONSENSUS_BRANCH_ID_ORCHARD, 4); + uint8_t personalization[16] = {0}; + MEMCPY(personalization, "ZcashSigHash", 12); + MEMCPY(personalization + 12, CONSENSUS_BRANCH_ID_ORCHARD, 4); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); - cx_hash_no_throw(&ctx.header, CX_LAST, input, inputlen, output, HASH_SIZE); + cx_hash_no_throw(&ctx.header, CX_LAST, input, inputlen, output, HASH_SIZE); } -static void signature_hash_v5(const uint8_t *input, uint8_t *start_signdata, uint8_t index, signable_input type, uint8_t *output) { - zemu_log_stack("signature_hash_v5"); - cx_blake2b_t ctx; - - uint8_t personalization[16] = {0}; - MEMCPY(personalization, "ZcashTxHash_", 12); - MEMCPY(personalization + 12, CONSENSUS_BRANCH_ID_ORCHARD, 4); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); - - uint8_t header_digest[32] = {0}; - uint8_t transparent_digest[32] = {0}; - uint8_t sapling_digest[32] = {0}; - uint8_t orchard_digest[32] = {0}; - - hash_header_txid_data(start_signdata, header_digest); - transparent_sig_digest(input, start_signdata, index, type, transparent_digest); - hash_sapling_txid_data(start_signdata, sapling_digest); - hash_empty_orchard_txid_data(orchard_digest); - - cx_hash_no_throw(&ctx.header, 0, header_digest, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, transparent_digest, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, sapling_digest, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, orchard_digest, HASH_SIZE, output, HASH_SIZE); +static void signature_hash_v5(const uint8_t *input, uint8_t *start_signdata, + uint8_t index, signable_input type, + uint8_t *output) { + zemu_log_stack("signature_hash_v5"); + cx_blake2b_t ctx; + + uint8_t personalization[16] = {0}; + MEMCPY(personalization, "ZcashTxHash_", 12); + MEMCPY(personalization + 12, CONSENSUS_BRANCH_ID_ORCHARD, 4); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); + + uint8_t header_digest[32] = {0}; + uint8_t transparent_digest[32] = {0}; + uint8_t sapling_digest[32] = {0}; + uint8_t orchard_digest[32] = {0}; + + hash_header_txid_data(start_signdata, header_digest); + transparent_sig_digest(input, start_signdata, index, type, + transparent_digest); + hash_sapling_txid_data(start_signdata, sapling_digest); + hash_empty_orchard_txid_data(orchard_digest); + + cx_hash_no_throw(&ctx.header, 0, header_digest, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, transparent_digest, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, sapling_digest, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, CX_LAST, orchard_digest, HASH_SIZE, output, + HASH_SIZE); } -void signature_hash(const uint8_t *txdata, uint8_t *start_signdata, uint16_t inputlen, const uint8_t tx_version, uint8_t *output){ - if (tx_version == TX_VERSION_SAPLING) { - signature_hash_v4(start_signdata, inputlen, output); - } - else if (tx_version == TX_VERSION_NU5) - { - signature_hash_v5(txdata, start_signdata, 0, shielded, output); - } +void signature_hash(const uint8_t *txdata, uint8_t *start_signdata, + uint16_t inputlen, const uint8_t tx_version, + uint8_t *output) { + if (tx_version == TX_VERSION_SAPLING) { + signature_hash_v4(start_signdata, inputlen, output); + } else if (tx_version == TX_VERSION_NU5) { + signature_hash_v5(txdata, start_signdata, 0, shielded, output); + } } -static void signature_script_hash_v4(const uint8_t *input, uint16_t inputlen, uint8_t *script, uint16_t scriptlen, uint8_t *output) { - cx_blake2b_t ctx; +static void signature_script_hash_v4(const uint8_t *input, uint16_t inputlen, + uint8_t *script, uint16_t scriptlen, + uint8_t *output) { + cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, "ZcashSigHash", 12); - MEMCPY(personalization + 12, CONSENSUS_BRANCH_ID_ORCHARD, 4); + uint8_t personalization[16] = {0}; + MEMCPY(personalization, "ZcashSigHash", 12); + MEMCPY(personalization + 12, CONSENSUS_BRANCH_ID_ORCHARD, 4); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); - cx_hash_no_throw(&ctx.header, 0, input, inputlen, NULL, 0); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); + cx_hash_no_throw(&ctx.header, 0, input, inputlen, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, script, scriptlen, output, HASH_SIZE); + cx_hash_no_throw(&ctx.header, CX_LAST, script, scriptlen, output, HASH_SIZE); } -void signature_script_hash(const uint8_t *input, uint8_t *start_signdata, uint16_t inputlen, uint8_t *script, uint16_t scriptlen, uint8_t index, const uint8_t tx_version, uint8_t *output) { - if (tx_version==TX_VERSION_SAPLING) { - signature_script_hash_v4(start_signdata, inputlen, script, scriptlen, output); - } - else if (tx_version == TX_VERSION_NU5) - { - signature_hash_v5(input, start_signdata, index, transparent, output); - } +void signature_script_hash(const uint8_t *input, uint8_t *start_signdata, + uint16_t inputlen, uint8_t *script, + uint16_t scriptlen, uint8_t index, + const uint8_t tx_version, uint8_t *output) { + if (tx_version == TX_VERSION_SAPLING) { + signature_script_hash_v4(start_signdata, inputlen, script, scriptlen, + output); + } else if (tx_version == TX_VERSION_NU5) { + signature_hash_v5(input, start_signdata, index, transparent, output); + } } - diff --git a/app/src/sighash.h b/app/src/sighash.h index a8e06da4..4e4dfbd4 100644 --- a/app/src/sighash.h +++ b/app/src/sighash.h @@ -1,24 +1,24 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once typedef enum { - transparent = 0, - shielded = 1, + transparent = 0, + shielded = 1, } signable_input; void sapling_transparent_prevouts_hash(const uint8_t *input, uint8_t *output); @@ -27,10 +27,17 @@ void sapling_transparent_sequence_hash(const uint8_t *input, uint8_t *output); void v4_transparent_outputs_hash(uint8_t *output); -void shielded_output_hash(const uint8_t *input, uint16_t inputlen, uint8_t *output); +void shielded_output_hash(const uint8_t *input, uint16_t inputlen, + uint8_t *output); -void shielded_spend_hash(const uint8_t *input, uint16_t inputlen, uint8_t *output); +void shielded_spend_hash(const uint8_t *input, uint16_t inputlen, + uint8_t *output); -void signature_hash(const uint8_t *txdata, uint8_t *start_signdata, uint16_t inputlen, const uint8_t tx_version, uint8_t *output); +void signature_hash(const uint8_t *txdata, uint8_t *start_signdata, + uint16_t inputlen, const uint8_t tx_version, + uint8_t *output); -void signature_script_hash(const uint8_t *input, uint8_t *start_signdata, uint16_t inputlen, uint8_t *script, uint16_t scriptlen, uint8_t index, const uint8_t tx_version, uint8_t *output); +void signature_script_hash(const uint8_t *input, uint8_t *start_signdata, + uint16_t inputlen, uint8_t *script, + uint16_t scriptlen, uint8_t index, + const uint8_t tx_version, uint8_t *output); diff --git a/app/src/txid.c b/app/src/txid.c index 66283a29..ff28732d 100644 --- a/app/src/txid.c +++ b/app/src/txid.c @@ -1,13 +1,13 @@ -#include -#include -#include -#include "os.h" #include "constants.h" #include "cx.h" +#include "index_NU5.h" +#include "index_sapling.h" #include "nvdata.h" +#include "os.h" #include "sighash.h" -#include "index_sapling.h" -#include "index_NU5.h" +#include +#include +#include // TxId level 1 node personalization #define ZCASH_HEADERS_HASH_PERSONALIZATION "ZTxIdHeadersHash" @@ -34,49 +34,49 @@ #define ZCASH_TRANSPARENT_AMOUNTS_HASH_PERSONALIZATION "ZTxTrAmountsHash" #define ZCASH_TRANSPARENT_SCRIPTS_HASH_PERSONALIZATION "ZTxTrScriptsHash" -#define SIGHASH_ALL 0x01 +#define SIGHASH_ALL 0x01 void nu5_transparent_prevouts_hash(const uint8_t *input, uint8_t *output) { - zemu_log_stack("nu5_transparent_prevouts_hash\n"); - const uint8_t n = t_inlist_len(); - cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, PIC(ZCASH_PREVOUTS_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); - - - if (n == 0) { - cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); - return; - } - - const uint8_t *data = input + INDEX_TIN_PREVOUT; - for (uint8_t i = 0; i < n - 1; i++, data += T_IN_TX_LEN) { - cx_hash_no_throw(&ctx.header, 0, data, PREVOUT_SIZE, NULL, 0); - } - cx_hash_no_throw(&ctx.header, CX_LAST, data, PREVOUT_SIZE, output, HASH_SIZE); + zemu_log_stack("nu5_transparent_prevouts_hash\n"); + const uint8_t n = t_inlist_len(); + cx_blake2b_t ctx; + uint8_t personalization[16] = {0}; + MEMCPY(personalization, PIC(ZCASH_PREVOUTS_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); + + if (n == 0) { + cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); + return; + } + + const uint8_t *data = input + INDEX_TIN_PREVOUT; + for (uint8_t i = 0; i < n - 1; i++, data += T_IN_TX_LEN) { + cx_hash_no_throw(&ctx.header, 0, data, PREVOUT_SIZE, NULL, 0); + } + cx_hash_no_throw(&ctx.header, CX_LAST, data, PREVOUT_SIZE, output, HASH_SIZE); } void nu5_transparent_sequence_hash(const uint8_t *input, uint8_t *output) { - zemu_log_stack("nu5_transparent_sequence_hash"); + zemu_log_stack("nu5_transparent_sequence_hash"); - const uint8_t n = t_inlist_len(); + const uint8_t n = t_inlist_len(); - cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, PIC(ZCASH_SEQUENCE_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); - - if (n == 0) { - cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); - return; - } + cx_blake2b_t ctx; + uint8_t personalization[16] = {0}; + MEMCPY(personalization, PIC(ZCASH_SEQUENCE_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); - const uint8_t *data = input + INDEX_TIN_SEQ; - for (uint8_t i = 0; i < n - 1; i++, data += T_IN_TX_LEN) { - cx_hash_no_throw(&ctx.header, 0, data, SEQUENCE_SIZE, NULL, 0); - } - cx_hash_no_throw(&ctx.header, CX_LAST, data, SEQUENCE_SIZE, output, HASH_SIZE); + if (n == 0) { + cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); + return; + } + + const uint8_t *data = input + INDEX_TIN_SEQ; + for (uint8_t i = 0; i < n - 1; i++, data += T_IN_TX_LEN) { + cx_hash_no_throw(&ctx.header, 0, data, SEQUENCE_SIZE, NULL, 0); + } + cx_hash_no_throw(&ctx.header, CX_LAST, data, SEQUENCE_SIZE, output, + HASH_SIZE); } /// Sequentially append the full serialized value of each transparent output @@ -84,334 +84,378 @@ void nu5_transparent_sequence_hash(const uint8_t *input, uint8_t *output) { /// In the case that no outputs are provided, this produces a default /// hash from just the personalization string. void nu5_transparent_outputs_hash(uint8_t *output) { - const uint8_t n = t_outlist_len(); + const uint8_t n = t_outlist_len(); - cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, PIC(ZCASH_OUTPUTS_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); + cx_blake2b_t ctx; + uint8_t personalization[16] = {0}; + MEMCPY(personalization, PIC(ZCASH_OUTPUTS_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); - if (n == 0) { - cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); - return; - } + if (n == 0) { + cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); + return; + } - uint8_t data[T_OUTPUT_SIZE]; - uint8_t i = 0; - for (; i < n - 1; i++) { - t_output_item_t *item = t_outlist_retrieve_item(i); - MEMCPY(data, (uint8_t * ) & (item->value), 8); - MEMCPY(data + 8, item->address, SCRIPT_SIZE); - cx_hash_no_throw(&ctx.header, 0, data, sizeof(data), NULL, 0); - } + uint8_t data[T_OUTPUT_SIZE]; + uint8_t i = 0; + for (; i < n - 1; i++) { t_output_item_t *item = t_outlist_retrieve_item(i); - MEMCPY(data, (uint8_t * ) & (item->value), 8); + MEMCPY(data, (uint8_t *)&(item->value), 8); MEMCPY(data + 8, item->address, SCRIPT_SIZE); - cx_hash_no_throw(&ctx.header, CX_LAST, data, sizeof(data), output, HASH_SIZE); + cx_hash_no_throw(&ctx.header, 0, data, sizeof(data), NULL, 0); + } + t_output_item_t *item = t_outlist_retrieve_item(i); + MEMCPY(data, (uint8_t *)&(item->value), 8); + MEMCPY(data + 8, item->address, SCRIPT_SIZE); + cx_hash_no_throw(&ctx.header, CX_LAST, data, sizeof(data), output, HASH_SIZE); } - -/// Implements [ZIP 244 section T.3a](https://zips.z.cash/zip-0244#t-3a-sapling-spends-digest) +/// Implements [ZIP 244 section +/// T.3a](https://zips.z.cash/zip-0244#t-3a-sapling-spends-digest) /// /// Write disjoint parts of each Sapling shielded spend to a pair of hashes: -/// * \[nullifier*\] - personalized with ZCASH_SAPLING_SPENDS_COMPACT_HASH_PERSONALIZATION -/// * \[(cv, anchor, rk, zkproof)*\] - personalized with ZCASH_SAPLING_SPENDS_NONCOMPACT_HASH_PERSONALIZATION +/// * \[nullifier*\] - personalized with +/// ZCASH_SAPLING_SPENDS_COMPACT_HASH_PERSONALIZATION +/// * \[(cv, anchor, rk, zkproof)*\] - personalized with +/// ZCASH_SAPLING_SPENDS_NONCOMPACT_HASH_PERSONALIZATION /// -/// Then, hash these together personalized by ZCASH_SAPLING_SPENDS_HASH_PERSONALIZATION -void nu5_hash_sapling_spends(const uint8_t *input, uint8_t *output) -{ - zemu_log_stack("nu5_hash_sapling_spends"); - const uint8_t n = spendlist_len(); - - cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, PIC(ZCASH_SAPLING_SPENDS_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); - - if (n == 0) { - cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); - return; - } - cx_blake2b_t ch_ctx; - uint8_t ch_personalization[16] = {0}; - MEMCPY(ch_personalization, PIC(ZCASH_SAPLING_SPENDS_COMPACT_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ch_ctx, 256, NULL, 0, (uint8_t *) ch_personalization, 16); - - cx_blake2b_t nh_ctx; - uint8_t nh_personalization[16] = {0}; - MEMCPY(nh_personalization, PIC(ZCASH_SAPLING_SPENDS_NONCOMPACT_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&nh_ctx, 256, NULL, 0, (uint8_t *) nh_personalization, 16); - - const uint8_t *nullifier_data = input + INDEX_SPEND_NF; - const uint8_t *cv_data = input + INDEX_SPEND_VALUECMT; - const uint8_t *anchor_data = input + INDEX_SPEND_ANCHOR; - const uint8_t *rk_data = input + INDEX_SPEND_RK; - for (uint8_t i = 0; i < n - 1; i++, - nullifier_data += SPEND_TX_LEN, - cv_data += SPEND_TX_LEN, - anchor_data += SPEND_TX_LEN, - rk_data += SPEND_TX_LEN ) - { - // build the hash of nullifiers separately for compact blocks. - cx_hash_no_throw(&ch_ctx.header, 0, nullifier_data, NULLIFIER_SIZE, NULL, 0); - - cx_hash_no_throw(&nh_ctx.header, 0, cv_data, VALUE_COMMITMENT_SIZE, NULL, 0); - cx_hash_no_throw(&nh_ctx.header, 0, anchor_data, ANCHOR_SIZE, NULL, 0); - cx_hash_no_throw(&nh_ctx.header, 0, rk_data, RK_SIZE, NULL, 0); - } - - uint8_t ch_out[HASH_SIZE] = {0}; - cx_hash_no_throw(&ch_ctx.header, CX_LAST, nullifier_data, NULLIFIER_SIZE, (uint8_t *) ch_out, HASH_SIZE); - - uint8_t nh_out[HASH_SIZE]={0}; - cx_hash_no_throw(&nh_ctx.header, 0, cv_data, VALUE_COMMITMENT_SIZE, NULL, 0); +/// Then, hash these together personalized by +/// ZCASH_SAPLING_SPENDS_HASH_PERSONALIZATION +void nu5_hash_sapling_spends(const uint8_t *input, uint8_t *output) { + zemu_log_stack("nu5_hash_sapling_spends"); + const uint8_t n = spendlist_len(); + + cx_blake2b_t ctx; + uint8_t personalization[16] = {0}; + MEMCPY(personalization, PIC(ZCASH_SAPLING_SPENDS_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); + + if (n == 0) { + cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); + return; + } + cx_blake2b_t ch_ctx; + uint8_t ch_personalization[16] = {0}; + MEMCPY(ch_personalization, + PIC(ZCASH_SAPLING_SPENDS_COMPACT_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ch_ctx, 256, NULL, 0, + (uint8_t *)ch_personalization, 16); + + cx_blake2b_t nh_ctx; + uint8_t nh_personalization[16] = {0}; + MEMCPY(nh_personalization, + PIC(ZCASH_SAPLING_SPENDS_NONCOMPACT_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&nh_ctx, 256, NULL, 0, + (uint8_t *)nh_personalization, 16); + + const uint8_t *nullifier_data = input + INDEX_SPEND_NF; + const uint8_t *cv_data = input + INDEX_SPEND_VALUECMT; + const uint8_t *anchor_data = input + INDEX_SPEND_ANCHOR; + const uint8_t *rk_data = input + INDEX_SPEND_RK; + for (uint8_t i = 0; i < n - 1; i++, nullifier_data += SPEND_TX_LEN, + cv_data += SPEND_TX_LEN, anchor_data += SPEND_TX_LEN, + rk_data += SPEND_TX_LEN) { + // build the hash of nullifiers separately for compact blocks. + cx_hash_no_throw(&ch_ctx.header, 0, nullifier_data, NULLIFIER_SIZE, NULL, + 0); + + cx_hash_no_throw(&nh_ctx.header, 0, cv_data, VALUE_COMMITMENT_SIZE, NULL, + 0); cx_hash_no_throw(&nh_ctx.header, 0, anchor_data, ANCHOR_SIZE, NULL, 0); - cx_hash_no_throw(&nh_ctx.header, CX_LAST, rk_data, RK_SIZE, (uint8_t *) nh_out, HASH_SIZE); - - cx_hash_no_throw(&ctx.header, 0, (uint8_t *) ch_out, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, (uint8_t *) nh_out, HASH_SIZE, output, HASH_SIZE); + cx_hash_no_throw(&nh_ctx.header, 0, rk_data, RK_SIZE, NULL, 0); + } + + uint8_t ch_out[HASH_SIZE] = {0}; + cx_hash_no_throw(&ch_ctx.header, CX_LAST, nullifier_data, NULLIFIER_SIZE, + (uint8_t *)ch_out, HASH_SIZE); + + uint8_t nh_out[HASH_SIZE] = {0}; + cx_hash_no_throw(&nh_ctx.header, 0, cv_data, VALUE_COMMITMENT_SIZE, NULL, 0); + cx_hash_no_throw(&nh_ctx.header, 0, anchor_data, ANCHOR_SIZE, NULL, 0); + cx_hash_no_throw(&nh_ctx.header, CX_LAST, rk_data, RK_SIZE, (uint8_t *)nh_out, + HASH_SIZE); + + cx_hash_no_throw(&ctx.header, 0, (uint8_t *)ch_out, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, CX_LAST, (uint8_t *)nh_out, HASH_SIZE, output, + HASH_SIZE); } -/// Implements [ZIP 244 section T.3b](https://zips.z.cash/zip-0244#t-3b-sapling-outputs-digest) +/// Implements [ZIP 244 section +/// T.3b](https://zips.z.cash/zip-0244#t-3b-sapling-outputs-digest) /// /// Write disjoint parts of each Sapling shielded output as 3 separate hashes: -/// * \[(cmu, epk, enc_ciphertext\[..52\])*\] personalized with ZCASH_SAPLING_OUTPUTS_COMPACT_HASH_PERSONALIZATION -/// * \[enc_ciphertext\[52..564\]*\] (memo ciphertexts) personalized with ZCASH_SAPLING_OUTPUTS_MEMOS_HASH_PERSONALIZATION -/// * \[(cv, enc_ciphertext\[564..\], out_ciphertext, zkproof)*\] personalized with ZCASH_SAPLING_OUTPUTS_NONCOMPACT_HASH_PERSONALIZATION +/// * \[(cmu, epk, enc_ciphertext\[..52\])*\] personalized with +/// ZCASH_SAPLING_OUTPUTS_COMPACT_HASH_PERSONALIZATION +/// * \[enc_ciphertext\[52..564\]*\] (memo ciphertexts) personalized with +/// ZCASH_SAPLING_OUTPUTS_MEMOS_HASH_PERSONALIZATION +/// * \[(cv, enc_ciphertext\[564..\], out_ciphertext, zkproof)*\] personalized +/// with ZCASH_SAPLING_OUTPUTS_NONCOMPACT_HASH_PERSONALIZATION /// -/// Then, hash these together personalized with ZCASH_SAPLING_OUTPUTS_HASH_PERSONALIZATION -void nu5_hash_sapling_outputs(const uint8_t *input, uint8_t *output){ - zemu_log_stack("nu5_hash_sapling_outputs"); - const uint8_t n = outputlist_len(); - - cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, PIC(ZCASH_SAPLING_OUTPUTS_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); - - if (n == 0) { - cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); - return; - } - - cx_blake2b_t ch_ctx; - uint8_t ch_personalization[16] = {0}; - MEMCPY(ch_personalization, PIC(ZCASH_SAPLING_OUTPUTS_COMPACT_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ch_ctx, 256, NULL, 0, (uint8_t *) ch_personalization, 16); - - cx_blake2b_t mh_ctx; - uint8_t mh_personalization[16] = {0}; - MEMCPY(mh_personalization, PIC(ZCASH_SAPLING_OUTPUTS_MEMOS_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&mh_ctx, 256, NULL, 0, (uint8_t *) mh_personalization, 16); - - cx_blake2b_t nh_ctx; - uint8_t nh_personalization[16] = {0}; - MEMCPY(nh_personalization, PIC(ZCASH_SAPLING_OUTPUTS_NONCOMPACT_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&nh_ctx, 256, NULL, 0, (uint8_t *) nh_personalization, 16); - - const uint8_t *cmu = input + INDEX_OUTPUT_NOTECMT; - const uint8_t *ephemeral_key = input + INDEX_OUTPUT_EPK; - const uint8_t *enc_ciphertext = input + INDEX_OUTPUT_ENC; - - - const uint8_t *enc_ciphertext_memo = input + INDEX_OUTPUT_ENC_MEMO; - - const uint8_t *cv = input + INDEX_OUTPUT_VALUECMT; - const uint8_t *enc_ciphertext_aead_tag = input + INDEX_OUTPUT_ENC_AEAD_TAG; - const uint8_t *out_ciphertext = input + INDEX_OUTPUT_OUT; - - for (uint8_t i = 0; i < n - 1; i++, - cmu += OUTPUT_TX_LEN, - ephemeral_key += OUTPUT_TX_LEN, - enc_ciphertext += OUTPUT_TX_LEN, - enc_ciphertext_memo += OUTPUT_TX_LEN, - cv += OUTPUT_TX_LEN, - enc_ciphertext_aead_tag += OUTPUT_TX_LEN, - out_ciphertext += OUTPUT_TX_LEN) - { - cx_hash_no_throw(&ch_ctx.header, 0, cmu, NOTE_COMMITMENT_SIZE, NULL, 0); - cx_hash_no_throw(&ch_ctx.header, 0, ephemeral_key, EPK_SIZE, NULL, 0); - cx_hash_no_throw(&ch_ctx.header, 0, enc_ciphertext, 52, NULL, 0); - - cx_hash_no_throw(&mh_ctx.header, 0, enc_ciphertext_memo, OUTPUT_ENC_MEMO_SIZE, NULL, 0); - - cx_hash_no_throw(&nh_ctx.header, 0, cv, VALUE_COMMITMENT_SIZE, NULL, 0); - cx_hash_no_throw(&nh_ctx.header, 0, enc_ciphertext_aead_tag, OUTPUT_ENC_AEAD_TAG_SIZE, NULL, 0); - cx_hash_no_throw(&nh_ctx.header, 0, out_ciphertext, OUTPUT_OUT_SIZE, NULL, 0); - } - - uint8_t ch_out[HASH_SIZE] = {0}; - cx_hash_no_throw(&ch_ctx.header, 0, cmu, NOTE_COMMITMENT_SIZE, NULL, 0); - cx_hash_no_throw(&ch_ctx.header, 0, ephemeral_key, EPK_SIZE, NULL, 0); - cx_hash_no_throw(&ch_ctx.header, CX_LAST, enc_ciphertext, 52, ch_out, HASH_SIZE); - - uint8_t mh_out[HASH_SIZE] = {0}; - cx_hash_no_throw(&mh_ctx.header, CX_LAST, enc_ciphertext_memo, OUTPUT_ENC_MEMO_SIZE, (uint8_t *) mh_out, HASH_SIZE); - +/// Then, hash these together personalized with +/// ZCASH_SAPLING_OUTPUTS_HASH_PERSONALIZATION +void nu5_hash_sapling_outputs(const uint8_t *input, uint8_t *output) { + zemu_log_stack("nu5_hash_sapling_outputs"); + const uint8_t n = outputlist_len(); + + cx_blake2b_t ctx; + uint8_t personalization[16] = {0}; + MEMCPY(personalization, PIC(ZCASH_SAPLING_OUTPUTS_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); + + if (n == 0) { + cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); + return; + } + + cx_blake2b_t ch_ctx; + uint8_t ch_personalization[16] = {0}; + MEMCPY(ch_personalization, + PIC(ZCASH_SAPLING_OUTPUTS_COMPACT_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ch_ctx, 256, NULL, 0, + (uint8_t *)ch_personalization, 16); + + cx_blake2b_t mh_ctx; + uint8_t mh_personalization[16] = {0}; + MEMCPY(mh_personalization, + PIC(ZCASH_SAPLING_OUTPUTS_MEMOS_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&mh_ctx, 256, NULL, 0, + (uint8_t *)mh_personalization, 16); + + cx_blake2b_t nh_ctx; + uint8_t nh_personalization[16] = {0}; + MEMCPY(nh_personalization, + PIC(ZCASH_SAPLING_OUTPUTS_NONCOMPACT_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&nh_ctx, 256, NULL, 0, + (uint8_t *)nh_personalization, 16); + + const uint8_t *cmu = input + INDEX_OUTPUT_NOTECMT; + const uint8_t *ephemeral_key = input + INDEX_OUTPUT_EPK; + const uint8_t *enc_ciphertext = input + INDEX_OUTPUT_ENC; + + const uint8_t *enc_ciphertext_memo = input + INDEX_OUTPUT_ENC_MEMO; + + const uint8_t *cv = input + INDEX_OUTPUT_VALUECMT; + const uint8_t *enc_ciphertext_aead_tag = input + INDEX_OUTPUT_ENC_AEAD_TAG; + const uint8_t *out_ciphertext = input + INDEX_OUTPUT_OUT; + + for (uint8_t i = 0; i < n - 1; i++, cmu += OUTPUT_TX_LEN, + ephemeral_key += OUTPUT_TX_LEN, enc_ciphertext += OUTPUT_TX_LEN, + enc_ciphertext_memo += OUTPUT_TX_LEN, cv += OUTPUT_TX_LEN, + enc_ciphertext_aead_tag += OUTPUT_TX_LEN, + out_ciphertext += OUTPUT_TX_LEN) { + cx_hash_no_throw(&ch_ctx.header, 0, cmu, NOTE_COMMITMENT_SIZE, NULL, 0); + cx_hash_no_throw(&ch_ctx.header, 0, ephemeral_key, EPK_SIZE, NULL, 0); + cx_hash_no_throw(&ch_ctx.header, 0, enc_ciphertext, 52, NULL, 0); + + cx_hash_no_throw(&mh_ctx.header, 0, enc_ciphertext_memo, + OUTPUT_ENC_MEMO_SIZE, NULL, 0); - uint8_t nh_out[HASH_SIZE] = {0}; cx_hash_no_throw(&nh_ctx.header, 0, cv, VALUE_COMMITMENT_SIZE, NULL, 0); - cx_hash_no_throw(&nh_ctx.header, 0, enc_ciphertext_aead_tag, OUTPUT_ENC_AEAD_TAG_SIZE, NULL, 0); - cx_hash_no_throw(&nh_ctx.header, CX_LAST, out_ciphertext, OUTPUT_OUT_SIZE, nh_out, HASH_SIZE); - - cx_hash_no_throw(&ctx.header, 0, ch_out, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, mh_out, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, nh_out, HASH_SIZE, output, HASH_SIZE); + cx_hash_no_throw(&nh_ctx.header, 0, enc_ciphertext_aead_tag, + OUTPUT_ENC_AEAD_TAG_SIZE, NULL, 0); + cx_hash_no_throw(&nh_ctx.header, 0, out_ciphertext, OUTPUT_OUT_SIZE, NULL, + 0); + } + + uint8_t ch_out[HASH_SIZE] = {0}; + cx_hash_no_throw(&ch_ctx.header, 0, cmu, NOTE_COMMITMENT_SIZE, NULL, 0); + cx_hash_no_throw(&ch_ctx.header, 0, ephemeral_key, EPK_SIZE, NULL, 0); + cx_hash_no_throw(&ch_ctx.header, CX_LAST, enc_ciphertext, 52, ch_out, + HASH_SIZE); + + uint8_t mh_out[HASH_SIZE] = {0}; + cx_hash_no_throw(&mh_ctx.header, CX_LAST, enc_ciphertext_memo, + OUTPUT_ENC_MEMO_SIZE, (uint8_t *)mh_out, HASH_SIZE); + + uint8_t nh_out[HASH_SIZE] = {0}; + cx_hash_no_throw(&nh_ctx.header, 0, cv, VALUE_COMMITMENT_SIZE, NULL, 0); + cx_hash_no_throw(&nh_ctx.header, 0, enc_ciphertext_aead_tag, + OUTPUT_ENC_AEAD_TAG_SIZE, NULL, 0); + cx_hash_no_throw(&nh_ctx.header, CX_LAST, out_ciphertext, OUTPUT_OUT_SIZE, + nh_out, HASH_SIZE); + + cx_hash_no_throw(&ctx.header, 0, ch_out, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, mh_out, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, CX_LAST, nh_out, HASH_SIZE, output, HASH_SIZE); } /// The txid commits to the hash of all transparent outputs. The /// prevout and sequence_hash components of txid -void hash_header_txid_data(const uint8_t *input, uint8_t *output){ - zemu_log_stack("hash_header_txid_data"); - cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, PIC(ZCASH_HEADERS_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); - - const uint8_t *version = input + NU5_INDEX_HASH_VERSION; - const uint8_t *version_group_id = input + NU5_INDEX_HASH_VERSION_GROUP_ID; - const uint8_t *consensus_branch_id = input + NU5_INDEX_HASH_CONSENSUS_BRANCH_ID; - const uint8_t *lock_time = input + NU5_INDEX_HASH_LOCK_TIME; - const uint8_t *expiry_height = input + NU5_INDEX_EXPIRY_HEIGHT; - - - cx_hash_no_throw(&ctx.header, 0, version, 4, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, version_group_id, 4, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, consensus_branch_id, 4, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, lock_time, 4, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, expiry_height, 4, output, HASH_SIZE); +void hash_header_txid_data(const uint8_t *input, uint8_t *output) { + zemu_log_stack("hash_header_txid_data"); + cx_blake2b_t ctx; + uint8_t personalization[16] = {0}; + MEMCPY(personalization, PIC(ZCASH_HEADERS_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); + + const uint8_t *version = input + NU5_INDEX_HASH_VERSION; + const uint8_t *version_group_id = input + NU5_INDEX_HASH_VERSION_GROUP_ID; + const uint8_t *consensus_branch_id = + input + NU5_INDEX_HASH_CONSENSUS_BRANCH_ID; + const uint8_t *lock_time = input + NU5_INDEX_HASH_LOCK_TIME; + const uint8_t *expiry_height = input + NU5_INDEX_EXPIRY_HEIGHT; + + cx_hash_no_throw(&ctx.header, 0, version, 4, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, version_group_id, 4, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, consensus_branch_id, 4, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, lock_time, 4, NULL, 0); + cx_hash_no_throw(&ctx.header, CX_LAST, expiry_height, 4, output, HASH_SIZE); } void hash_transparent_txid_data(const uint8_t *input, uint8_t *output) { - zemu_log_stack("hash_transparent_txid_data"); - cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, PIC(ZCASH_TRANSPARENT_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); + zemu_log_stack("hash_transparent_txid_data"); + cx_blake2b_t ctx; + uint8_t personalization[16] = {0}; + MEMCPY(personalization, PIC(ZCASH_TRANSPARENT_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); + + if (t_inlist_len() + t_outlist_len() > 0) { + const uint8_t *prevout_digest = input + NU5_INDEX_HASH_PREVOUTSHASH; + const uint8_t *sequence_digest = input + NU5_INDEX_HASH_SEQUENCEHASH; + const uint8_t *outputs_digest = input + NU5_INDEX_HASH_OUTPUTSHASH; + + cx_hash_no_throw(&ctx.header, 0, prevout_digest, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, sequence_digest, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, CX_LAST, outputs_digest, HASH_SIZE, output, + HASH_SIZE); + } else { + cx_hash_no_throw(&ctx.header, CX_LAST, NULL, 0, output, HASH_SIZE); + } +} - if (t_inlist_len() + t_outlist_len() > 0) { - const uint8_t *prevout_digest = input + NU5_INDEX_HASH_PREVOUTSHASH; - const uint8_t *sequence_digest = input + NU5_INDEX_HASH_SEQUENCEHASH; - const uint8_t *outputs_digest = input + NU5_INDEX_HASH_OUTPUTSHASH; +void transparent_sig_digest(const uint8_t *input, uint8_t *start_signdata, + uint8_t index, signable_input type, + uint8_t *output) { + zemu_log_stack("transparent_sig_digest"); - cx_hash_no_throw(&ctx.header, 0, prevout_digest, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, sequence_digest, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, outputs_digest, HASH_SIZE, output, HASH_SIZE); - } - else{ - cx_hash_no_throw(&ctx.header, CX_LAST, NULL, 0, output, HASH_SIZE); - } -} + if (t_inlist_len() == 0) { + hash_transparent_txid_data(start_signdata, output); + } else { + // the following implies that flag_anyonecanpay = flag_single = flag_none = + // false + uint8_t hash_type = SIGHASH_ALL; -void transparent_sig_digest(const uint8_t *input, uint8_t *start_signdata, uint8_t index,signable_input type, uint8_t *output) { - zemu_log_stack("transparent_sig_digest"); + const uint8_t *prevout_digest = + start_signdata + NU5_INDEX_HASH_PREVOUTSHASH; - if (t_inlist_len()==0){ - hash_transparent_txid_data(start_signdata,output); + // compute amounts digest + cx_blake2b_t ctx_amounts; + uint8_t personalization[16] = {0}; + MEMCPY(personalization, PIC(ZCASH_TRANSPARENT_AMOUNTS_HASH_PERSONALIZATION), + 16); + cx_blake2b_init2_no_throw(&ctx_amounts, 256, NULL, 0, + (uint8_t *)personalization, 16); + uint64_t amount = 0; + uint8_t amounts_digest[HASH_SIZE] = {0}; + for (uint8_t i = 0; i < t_inlist_len() - 1; ++i) { + amount = t_inlist_retrieve_item_amount(i); + cx_hash_no_throw(&ctx_amounts.header, 0, (uint8_t *)&amount, + sizeof(uint64_t), NULL, 0); } - else{ - // the following implies that flag_anyonecanpay = flag_single = flag_none = false - uint8_t hash_type = SIGHASH_ALL; - - const uint8_t *prevout_digest = start_signdata + NU5_INDEX_HASH_PREVOUTSHASH; - - // compute amounts digest - cx_blake2b_t ctx_amounts; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, PIC(ZCASH_TRANSPARENT_AMOUNTS_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx_amounts, 256, NULL, 0, (uint8_t *) personalization, 16); - uint64_t amount = 0; - uint8_t amounts_digest[HASH_SIZE] = {0}; - for (uint8_t i = 0; i < t_inlist_len()-1; ++i) { - amount = t_inlist_retrieve_item_amount(i); - cx_hash_no_throw(&ctx_amounts.header, 0, (uint8_t *) &amount, sizeof(uint64_t), NULL, 0); - } - amount = t_inlist_retrieve_item_amount(t_inlist_len()-1); - cx_hash_no_throw(&ctx_amounts.header, CX_LAST, (uint8_t *) &amount, sizeof(uint64_t), amounts_digest, HASH_SIZE); - MEMZERO(personalization, 16); - - cx_blake2b_t ctx_scripts; - MEMCPY(personalization, PIC(ZCASH_TRANSPARENT_SCRIPTS_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx_scripts, 256, NULL, 0, (uint8_t *) personalization, 16); - uint8_t scripts[SCRIPT_SIZE]; - uint8_t scripts_digest[HASH_SIZE] = {0}; - for (uint8_t i = 0; i < t_inlist_len()-1; ++i) { - t_inlist_retrieve_item_script(i, scripts); - cx_hash_no_throw(&ctx_scripts.header, 0, scripts, sizeof(scripts), NULL, 0); - MEMZERO(scripts, SCRIPT_SIZE); - } - t_inlist_retrieve_item_script(t_inlist_len()-1, scripts); - cx_hash_no_throw(&ctx_scripts.header, CX_LAST, scripts, SCRIPT_SIZE, scripts_digest, HASH_SIZE); - MEMZERO(personalization, 16); - - const uint8_t *sequence_digest = start_signdata + NU5_INDEX_HASH_SEQUENCEHASH; - const uint8_t *outputs_digest = start_signdata + NU5_INDEX_HASH_OUTPUTSHASH; - - cx_blake2b_t ctx_txin_sig_digest; - uint8_t txin_sig_digest[HASH_SIZE] = {0}; - MEMCPY(personalization, PIC(ZCASH_TRANSPARENT_INPUT_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx_txin_sig_digest, 256, NULL, 0, (uint8_t *) personalization, 16); - if (type == transparent){ - const t_input_item_t *item = t_inlist_retrieve_item(index); - - const uint8_t *prevout_data = input + index * T_IN_TX_LEN + INDEX_TIN_PREVOUT; - cx_hash_no_throw(&ctx_txin_sig_digest.header, 0, prevout_data, PREVOUT_SIZE, NULL, 0); - - uint64_t value = item->value; - cx_hash_no_throw(&ctx_txin_sig_digest.header, 0, (uint8_t *) &value, sizeof(uint64_t), NULL, 0); - - const uint8_t *script = item-> script; - cx_hash_no_throw(&ctx_txin_sig_digest.header, 0, script, SCRIPT_SIZE, NULL, 0); - - const uint8_t *sequence_data = input + index * T_IN_TX_LEN + INDEX_TIN_SEQ; - cx_hash_no_throw(&ctx_txin_sig_digest.header, 0, sequence_data, SEQUENCE_SIZE, NULL, 0); - } - cx_hash_no_throw(&ctx_txin_sig_digest.header, CX_LAST, NULL, 0, txin_sig_digest, HASH_SIZE); - MEMZERO(personalization,16); - - cx_blake2b_t ctx; - MEMCPY(personalization, PIC(ZCASH_TRANSPARENT_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); - - cx_hash_no_throw(&ctx.header, 0, &hash_type, sizeof(uint8_t), NULL, 0); - cx_hash_no_throw(&ctx.header, 0, prevout_digest, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, amounts_digest, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, scripts_digest, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, sequence_digest, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, outputs_digest, HASH_SIZE, NULL, 0); - - cx_hash_no_throw(&ctx.header, CX_LAST, txin_sig_digest, HASH_SIZE, output, HASH_SIZE); - + amount = t_inlist_retrieve_item_amount(t_inlist_len() - 1); + cx_hash_no_throw(&ctx_amounts.header, CX_LAST, (uint8_t *)&amount, + sizeof(uint64_t), amounts_digest, HASH_SIZE); + MEMZERO(personalization, 16); + + cx_blake2b_t ctx_scripts; + MEMCPY(personalization, PIC(ZCASH_TRANSPARENT_SCRIPTS_HASH_PERSONALIZATION), + 16); + cx_blake2b_init2_no_throw(&ctx_scripts, 256, NULL, 0, + (uint8_t *)personalization, 16); + uint8_t scripts[SCRIPT_SIZE]; + uint8_t scripts_digest[HASH_SIZE] = {0}; + for (uint8_t i = 0; i < t_inlist_len() - 1; ++i) { + t_inlist_retrieve_item_script(i, scripts); + cx_hash_no_throw(&ctx_scripts.header, 0, scripts, sizeof(scripts), NULL, + 0); + MEMZERO(scripts, SCRIPT_SIZE); } -} + t_inlist_retrieve_item_script(t_inlist_len() - 1, scripts); + cx_hash_no_throw(&ctx_scripts.header, CX_LAST, scripts, SCRIPT_SIZE, + scripts_digest, HASH_SIZE); + MEMZERO(personalization, 16); + + const uint8_t *sequence_digest = + start_signdata + NU5_INDEX_HASH_SEQUENCEHASH; + const uint8_t *outputs_digest = start_signdata + NU5_INDEX_HASH_OUTPUTSHASH; + + cx_blake2b_t ctx_txin_sig_digest; + uint8_t txin_sig_digest[HASH_SIZE] = {0}; + MEMCPY(personalization, PIC(ZCASH_TRANSPARENT_INPUT_HASH_PERSONALIZATION), + 16); + cx_blake2b_init2_no_throw(&ctx_txin_sig_digest, 256, NULL, 0, + (uint8_t *)personalization, 16); + if (type == transparent) { + const t_input_item_t *item = t_inlist_retrieve_item(index); + + const uint8_t *prevout_data = + input + index * T_IN_TX_LEN + INDEX_TIN_PREVOUT; + cx_hash_no_throw(&ctx_txin_sig_digest.header, 0, prevout_data, + PREVOUT_SIZE, NULL, 0); + + uint64_t value = item->value; + cx_hash_no_throw(&ctx_txin_sig_digest.header, 0, (uint8_t *)&value, + sizeof(uint64_t), NULL, 0); + + const uint8_t *script = item->script; + cx_hash_no_throw(&ctx_txin_sig_digest.header, 0, script, SCRIPT_SIZE, + NULL, 0); + + const uint8_t *sequence_data = + input + index * T_IN_TX_LEN + INDEX_TIN_SEQ; + cx_hash_no_throw(&ctx_txin_sig_digest.header, 0, sequence_data, + SEQUENCE_SIZE, NULL, 0); + } + cx_hash_no_throw(&ctx_txin_sig_digest.header, CX_LAST, NULL, 0, + txin_sig_digest, HASH_SIZE); + MEMZERO(personalization, 16); -void hash_sapling_txid_data(const uint8_t *input, uint8_t *output) { - zemu_log_stack("hash_sapling_txid_data"); cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, PIC(ZCASH_SAPLING_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); - - if (spendlist_len() + outputlist_len() > 0) { - const uint8_t *hash_sapling_spends = input + NU5_INDEX_HASH_SHIELDEDSPENDHASH; - const uint8_t *hash_sapling_outputs = input + NU5_INDEX_HASH_SHIELDEDOUTPUTHASH; - const uint8_t *value_balance = input + NU5_INDEX_HASH_VALUEBALANCE; + MEMCPY(personalization, PIC(ZCASH_TRANSPARENT_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, + 16); + + cx_hash_no_throw(&ctx.header, 0, &hash_type, sizeof(uint8_t), NULL, 0); + cx_hash_no_throw(&ctx.header, 0, prevout_digest, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, amounts_digest, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, scripts_digest, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, sequence_digest, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, outputs_digest, HASH_SIZE, NULL, 0); + + cx_hash_no_throw(&ctx.header, CX_LAST, txin_sig_digest, HASH_SIZE, output, + HASH_SIZE); + } +} - cx_hash_no_throw(&ctx.header, 0, hash_sapling_spends, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, 0, hash_sapling_outputs, HASH_SIZE, NULL, 0); - cx_hash_no_throw(&ctx.header, CX_LAST, value_balance, NU5_VALUEBALANCE_SIZE, output, HASH_SIZE); - } - else{ - cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); - } +void hash_sapling_txid_data(const uint8_t *input, uint8_t *output) { + zemu_log_stack("hash_sapling_txid_data"); + cx_blake2b_t ctx; + uint8_t personalization[16] = {0}; + MEMCPY(personalization, PIC(ZCASH_SAPLING_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); + + if (spendlist_len() + outputlist_len() > 0) { + const uint8_t *hash_sapling_spends = + input + NU5_INDEX_HASH_SHIELDEDSPENDHASH; + const uint8_t *hash_sapling_outputs = + input + NU5_INDEX_HASH_SHIELDEDOUTPUTHASH; + const uint8_t *value_balance = input + NU5_INDEX_HASH_VALUEBALANCE; + + cx_hash_no_throw(&ctx.header, 0, hash_sapling_spends, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, 0, hash_sapling_outputs, HASH_SIZE, NULL, 0); + cx_hash_no_throw(&ctx.header, CX_LAST, value_balance, NU5_VALUEBALANCE_SIZE, + output, HASH_SIZE); + } else { + cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); + } } void hash_empty_orchard_txid_data(uint8_t *output) { - cx_blake2b_t ctx; - uint8_t personalization[16] = {0}; - MEMCPY(personalization, PIC(ZCASH_ORCHARD_HASH_PERSONALIZATION), 16); - cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *) personalization, 16); + cx_blake2b_t ctx; + uint8_t personalization[16] = {0}; + MEMCPY(personalization, PIC(ZCASH_ORCHARD_HASH_PERSONALIZATION), 16); + cx_blake2b_init2_no_throw(&ctx, 256, NULL, 0, (uint8_t *)personalization, 16); - cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); + cx_hash_no_throw(&ctx.header, CX_LAST, 0, 0, output, HASH_SIZE); } diff --git a/app/src/txid.h b/app/src/txid.h index 97d3ab6a..156df9ec 100644 --- a/app/src/txid.h +++ b/app/src/txid.h @@ -1,18 +1,18 @@ /******************************************************************************* -* (c) 2018 -2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 -2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -30,7 +30,9 @@ void hash_header_txid_data(const uint8_t *input, uint8_t *output); void hash_transparent_txid_data(const uint8_t *input, uint8_t *output); -void transparent_sig_digest(const uint8_t *input, uint8_t *start_signdata, uint8_t index,signable_input type, uint8_t *output); +void transparent_sig_digest(const uint8_t *input, uint8_t *start_signdata, + uint8_t index, signable_input type, + uint8_t *output); void hash_sapling_txid_data(const uint8_t *input, uint8_t *output); diff --git a/app/src/zcash_apdu_errors.h b/app/src/zcash_apdu_errors.h index 3d9433f3..7f9be800 100644 --- a/app/src/zcash_apdu_errors.h +++ b/app/src/zcash_apdu_errors.h @@ -1,34 +1,34 @@ /******************************************************************************* -* (c) 2018 - 2022 Zondax AG -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * (c) 2018 - 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once // Specific APDU error codes for ZCash -#define APDU_CODE_DATA_TOO_LONG 0x6988 -#define APDU_CODE_EXTRACT_TRANSACTION_FAIL 0x6989 -#define APDU_CODE_HASH_MSG_BUF_FAIL 0x6990 -#define APDU_CODE_UNPROCESSED_TX 0x6991 -#define APDU_CODE_PREVOUT_INVALID 0x6992 -#define APDU_CODE_SEQUENCE_INVALID 0x6993 -#define APDU_CODE_OUTPUTS_INVALID 0x6994 -#define APDU_CODE_JOINSPLIT_INVALID 0x6995 -#define APDU_CODE_SPEND_INVALID 0x6996 -#define APDU_CODE_OUTPUT_CONTENT_INVALID 0x6997 -#define APDU_CODE_ENCRYPTION_INVALID 0x6998 -#define APDU_CODE_CHECK_SIGN_TR_FAIL 0x6999 -#define APDU_SIGN_SPEND_FAIL 0x69A0 -#define APDU_CODE_BAD_VALUEBALANCE 0x69A1 -#define APDU_CODE_UNHANDLED_TX_VERSION 0x69A2 +#define APDU_CODE_DATA_TOO_LONG 0x6988 +#define APDU_CODE_EXTRACT_TRANSACTION_FAIL 0x6989 +#define APDU_CODE_HASH_MSG_BUF_FAIL 0x6990 +#define APDU_CODE_UNPROCESSED_TX 0x6991 +#define APDU_CODE_PREVOUT_INVALID 0x6992 +#define APDU_CODE_SEQUENCE_INVALID 0x6993 +#define APDU_CODE_OUTPUTS_INVALID 0x6994 +#define APDU_CODE_JOINSPLIT_INVALID 0x6995 +#define APDU_CODE_SPEND_INVALID 0x6996 +#define APDU_CODE_OUTPUT_CONTENT_INVALID 0x6997 +#define APDU_CODE_ENCRYPTION_INVALID 0x6998 +#define APDU_CODE_CHECK_SIGN_TR_FAIL 0x6999 +#define APDU_SIGN_SPEND_FAIL 0x69A0 +#define APDU_CODE_BAD_VALUEBALANCE 0x69A1 +#define APDU_CODE_UNHANDLED_TX_VERSION 0x69A2 From f111c91721969b07d8d75fe5802c7283c8e23d0a Mon Sep 17 00:00:00 2001 From: becominginsane Date: Fri, 27 Oct 2023 03:15:26 +0800 Subject: [PATCH 2/3] fix: add git blame ignore revs --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..4e0800fa --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# clang-format whole repo +1782c0088b067ae7275c22658e326378f0481d9c From c371425275c4cd3b5ae352074b3400cc551dde4f Mon Sep 17 00:00:00 2001 From: becominginsane Date: Fri, 27 Oct 2023 03:47:02 +0800 Subject: [PATCH 3/3] fix: missing includes --- app/src/chacha.c | 2 -- app/src/chacha.h | 5 +++++ app/src/sighash.c | 1 - app/src/sighash.h | 2 ++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/chacha.c b/app/src/chacha.c index 598e3c8b..985b7600 100644 --- a/app/src/chacha.c +++ b/app/src/chacha.c @@ -20,8 +20,6 @@ #include "cx.h" #include "os.h" #include "zxmacros.h" -#include -#include #define U8TO32_LITTLE(p) \ (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \ diff --git a/app/src/chacha.h b/app/src/chacha.h index 9ac95ba5..a9414c0a 100644 --- a/app/src/chacha.h +++ b/app/src/chacha.h @@ -12,6 +12,11 @@ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#pragma once + +#include +#include + #if defined(__cplusplus) extern "C" { #endif diff --git a/app/src/sighash.c b/app/src/sighash.c index 7dfb9336..02a6d9c2 100644 --- a/app/src/sighash.c +++ b/app/src/sighash.c @@ -20,7 +20,6 @@ #include "nvdata.h" #include "os.h" #include "txid.h" -#include #include #include diff --git a/app/src/sighash.h b/app/src/sighash.h index 4e4dfbd4..e0a11c38 100644 --- a/app/src/sighash.h +++ b/app/src/sighash.h @@ -16,6 +16,8 @@ #pragma once +#include + typedef enum { transparent = 0, shielded = 1,