diff --git a/common/Firewall/sec_flash.c b/common/Firewall/sec_flash.c index 0054089a1..ad04106ae 100644 --- a/common/Firewall/sec_flash.c +++ b/common/Firewall/sec_flash.c @@ -73,7 +73,7 @@ #include "utils.h" #define SEC_FLASH_STRUCT_TLV_SIZE \ - (6 + 3 + (MAX_WALLETS_ALLOWED * (9 + sizeof(Wallet_Share_Data))) + 3 + \ + (6 + 3 + (MAX_WALLETS_ALLOWED * (12 + sizeof(Wallet_Share_Data))) + 3 + \ (MAX_KEYSTORE_ENTRY * ((4 * 3) + sizeof(Card_Keystore)))) #define FLASH_WRITE_PERM_STRUCTURE_SIZE sizeof(Flash_Perm_Struct) / 4 @@ -85,6 +85,7 @@ typedef enum Sec_Flash_tlv_tags { TAG_SEC_FLASH_WALLET_SHARE_STRUCT = 0x11, TAG_SEC_FLASH_WALLET_ID = 0x12, TAG_SEC_FLASH_WALLET_SHARE = 0x13, + TAG_SEC_FLASH_WALLET_NONCE = 0x14, TAG_SEC_FLASH_KEYSTORE = 0x30, TAG_SEC_FLASH_KEYSTORE_USED = 0x31, @@ -551,6 +552,11 @@ static void serialize_sec_fs_wallet(uint8_t *array, TAG_SEC_FLASH_WALLET_SHARE, BLOCK_SIZE, sec_fs->wallet_share_data[wallet_index].wallet_share); + fill_flash_tlv(array, + starting_index, + TAG_SEC_FLASH_WALLET_NONCE, + PADDED_NONCE_SIZE, + sec_fs->wallet_share_data[wallet_index].wallet_nonce); array[len_index] = (*starting_index) - len_index - 2; array[len_index + 1] = ((*starting_index) - len_index - 2) >> 8; @@ -710,6 +716,11 @@ static void deserialize_sec_fs_wallet(Wallet_Share_Data *wallet_share_data, break; } + case TAG_SEC_FLASH_WALLET_NONCE: { + memcpy(wallet_share_data->wallet_nonce, tlv + index + 2, size); + break; + } + case TAG_SEC_FLASH_WALLET_ID: { memcpy(wallet_share_data->wallet_id, tlv + index + 2, size); break; diff --git a/common/Firewall/sec_flash.h b/common/Firewall/sec_flash.h index d55b53943..e5cb39ef1 100644 --- a/common/Firewall/sec_flash.h +++ b/common/Firewall/sec_flash.h @@ -66,6 +66,8 @@ typedef struct Wallet_share { uint8_t wallet_id[WALLET_ID_SIZE]; ///< Wallet ID derived from seed uint8_t wallet_share[BLOCK_SIZE]; ///< Device's (5th) share derived from seed + uint8_t wallet_nonce[PADDED_NONCE_SIZE]; ///< Wallet's nonce including IV + ///< and version data } Wallet_Share_Data; #pragma pack(pop) diff --git a/common/coin_support/wallet.c b/common/coin_support/wallet.c index 1f5b92495..5b1f37491 100644 --- a/common/coin_support/wallet.c +++ b/common/coin_support/wallet.c @@ -114,7 +114,8 @@ bool encrypt_shares() { &ctx, wallet_shamir_data.mnemonic_shares[i], share, BLOCK_SIZE); chacha20poly1305_finish( &ctx, - (uint8_t *)(wallet_shamir_data.share_encryption_data[i] + NONCE_SIZE)); + (uint8_t *)(wallet_shamir_data.share_encryption_data[i] + + PADDED_NONCE_SIZE)); memcpy(wallet_shamir_data.mnemonic_shares[i], share, BLOCK_SIZE); } @@ -134,7 +135,8 @@ bool decrypt_shares() { &ctx, wallet_shamir_data.mnemonic_shares[i], share, BLOCK_SIZE); chacha20poly1305_finish( &ctx, - (uint8_t *)(wallet_shamir_data.share_encryption_data[i] + NONCE_SIZE)); + (uint8_t *)(wallet_shamir_data.share_encryption_data[i] + + PADDED_NONCE_SIZE)); // TODO: Add mac comparison for decryption verification memcpy(wallet_shamir_data.mnemonic_shares[i], share, BLOCK_SIZE); } diff --git a/common/coin_support/wallet.h b/common/coin_support/wallet.h index 9c0c503c0..b8e86ff78 100644 --- a/common/coin_support/wallet.h +++ b/common/coin_support/wallet.h @@ -28,7 +28,10 @@ CARD_VERSION_GIT_REV_SIZE) #define BLOCK_SIZE 32 -#define NONCE_SIZE 16 +#define NONCE_SIZE 12 +#define PADDED_NONCE_SIZE \ + NONCE_SIZE + 4 // 3 bytes as RFU and LSB as version byte +#define HASH_SIZE 32 #define WALLET_MAC_SIZE 16 #define PIN_SHARE_SIZE 80 #define CHECKSUM_SIZE 4 @@ -115,7 +118,7 @@ typedef struct Wallet { uint8_t wallet_info; uint8_t password_double_hash[BLOCK_SIZE]; - uint8_t wallet_share_with_mac_and_nonce[BLOCK_SIZE + NONCE_SIZE + + uint8_t wallet_share_with_mac_and_nonce[BLOCK_SIZE + PADDED_NONCE_SIZE + WALLET_MAC_SIZE]; uint8_t arbitrary_data_share[512]; @@ -156,7 +159,7 @@ typedef struct Wallet_shamir_data { }; uint8_t share_x_coords[TOTAL_NUMBER_OF_SHARES]; uint8_t share_encryption_data[TOTAL_NUMBER_OF_SHARES] - [NONCE_SIZE + WALLET_MAC_SIZE]; + [PADDED_NONCE_SIZE + WALLET_MAC_SIZE]; } Wallet_shamir_data; #pragma pack(pop) diff --git a/common/interfaces/card_interface/apdu.c b/common/interfaces/card_interface/apdu.c index 0214bbdf7..a0c1814f1 100644 --- a/common/interfaces/card_interface/apdu.c +++ b/common/interfaces/card_interface/apdu.c @@ -217,7 +217,7 @@ uint16_t create_apdu_add_wallet(const struct Wallet *wallet, uint8_t apdu[]) { fill_tlv(apdu, &index, INS_WALLET_SHARE, - BLOCK_SIZE + NONCE_SIZE + WALLET_MAC_SIZE, + BLOCK_SIZE + PADDED_NONCE_SIZE + WALLET_MAC_SIZE, wallet); fill_tlv(apdu, &index, INS_STRUCTURE_CHECKSUM, CHECKSUM_SIZE, wallet); fill_tlv(apdu, &index, INS_MIN_NO_OF_SHARES, 1, wallet); diff --git a/common/interfaces/flash_interface/flash_api.c b/common/interfaces/flash_interface/flash_api.c index a12bbe1e9..9018237ea 100644 --- a/common/interfaces/flash_interface/flash_api.c +++ b/common/interfaces/flash_interface/flash_api.c @@ -117,6 +117,29 @@ bool wallet_is_filled(uint8_t index, wallet_state *state_output) { return false; } +bool wallet_is_filled_with_share(uint8_t index) { + if (MAX_WALLETS_ALLOWED <= index) { + return false; + } + + /* Make sure that we always work on the latest RAM instance */ + get_flash_ram_instance(); + + wallet_state state = flash_ram_instance.wallets[index].state; + // Read card states without write attempt state + uint8_t cards_states = flash_ram_instance.wallets[index].cards_states & 0x0F; + + // If wallet state state is where share is present on device and card state is + // not zero, then wallet is filled + if (((UNVERIFIED_VALID_WALLET == state) || (VALID_WALLET == state) || + (INVALID_WALLET == state)) && + (0x00 != cards_states)) { + return true; + } + + return false; +} + /** * @brief Save a new wallet on the flash * @@ -160,7 +183,8 @@ int add_wallet_to_flash(const Flash_Wallet *fwallet, uint32_t *index_OUT) { int add_wallet_share_to_sec_flash(const Flash_Wallet *fwallet, uint32_t *index_OUT, - const uint8_t *wallet_share) { + const uint8_t *wallet_share, + const uint8_t *wallet_nonce) { get_flash_ram_instance(); // to load get_sec_flash_ram_instance(); if (flash_ram_instance.wallet_count == MAX_WALLETS_ALLOWED) @@ -190,6 +214,9 @@ int add_wallet_share_to_sec_flash(const Flash_Wallet *fwallet, memcpy(sec_flash_instance.wallet_share_data[*index_OUT].wallet_share, wallet_share, BLOCK_SIZE); + memcpy(sec_flash_instance.wallet_share_data[*index_OUT].wallet_nonce, + wallet_nonce, + PADDED_NONCE_SIZE); sec_flash_struct_save(); return SUCCESS_; } @@ -230,7 +257,8 @@ int put_wallet_flash(const uint8_t index, const Flash_Wallet *wallet) { } int put_wallet_share_sec_flash(const uint8_t index, - const uint8_t *wallet_share) { + const uint8_t *wallet_share, + const uint8_t *wallet_nonce) { get_flash_ram_instance(); // to load get_sec_flash_ram_instance(); if (index >= MAX_WALLETS_ALLOWED) @@ -246,6 +274,9 @@ int put_wallet_share_sec_flash(const uint8_t index, memcpy(sec_flash_instance.wallet_share_data[index].wallet_share, wallet_share, BLOCK_SIZE); + memcpy(sec_flash_instance.wallet_share_data[index].wallet_nonce, + wallet_nonce, + PADDED_NONCE_SIZE); sec_flash_struct_save(); flash_ram_instance.wallets[index].state = VALID_WALLET; flash_struct_save(); @@ -531,6 +562,42 @@ int get_flash_wallet_share_by_name(const char *name, uint8_t *wallet_share) { return DOESNT_EXIST; } +int get_flash_wallet_nonce_by_name(const char *name, uint8_t *wallet_nonce) { + ASSERT(name != NULL); + ASSERT(wallet_nonce != NULL); + + get_flash_ram_instance(); // to load + get_sec_flash_ram_instance(); + size_t name_len = strnlen(name, NAME_SIZE); + if (name_len == 0 || name_len >= NAME_SIZE) + return INVALID_ARGUMENT; + uint8_t walletIndex = 0; + for (; walletIndex < MAX_WALLETS_ALLOWED; walletIndex++) { + if (!_wallet_is_filled(walletIndex)) + continue; + if (!strcmp( + (const char *)flash_ram_instance.wallets[walletIndex].wallet_name, + name)) { + if (is_wallet_share_not_present(walletIndex)) + return DOESNT_EXIST; + for (int i = 0; i < WALLET_ID_SIZE; i++) { + if (flash_ram_instance.wallets[walletIndex].wallet_id[i] != + sec_flash_instance.wallet_share_data[walletIndex].wallet_id[i]) { + flash_ram_instance.wallets[walletIndex].state = + VALID_WALLET_WITHOUT_DEVICE_SHARE; + flash_struct_save(); + return DOESNT_EXIST; + } + } + memcpy(wallet_nonce, + sec_flash_instance.wallet_share_data[walletIndex].wallet_nonce, + BLOCK_SIZE); + return SUCCESS_; + } + } + return DOESNT_EXIST; +} + /** * @brief Tells if wallet is in partial state * @@ -575,41 +642,35 @@ bool is_wallet_locked(const uint8_t wallet_index) { } // TODO: return codes for illegal and all -/** - * @brief Update the card states for the wallet at specified index (on deletion - * of the wallet from the given card number) - * - * @param index - * @param card_number - * @return int - */ int delete_from_kth_card_flash(const uint8_t index, const uint8_t card_number) { ASSERT(index < MAX_WALLETS_ALLOWED); get_flash_ram_instance(); // to load - flash_ram_instance.wallets[index].cards_states &= ~(1 << (card_number - 1)); + + // Reset card write state + RESET_Ith_BIT(flash_ram_instance.wallets[index].cards_states, + card_number - 1); + // Reset card write attempt state + RESET_Ith_BIT(flash_ram_instance.wallets[index].cards_states, + card_number - 1 + 4); + flash_struct_save(); return SUCCESS_; } // TODO: check for illegal arguments and all -/** - * @brief Tells if the wallet at specified index is already deleted from the - * given card number - * - * @param index - * @param card_number - * @return true - * @return false - */ bool card_already_deleted_flash(const uint8_t index, const uint8_t card_number) { ASSERT(index < MAX_WALLETS_ALLOWED); get_flash_ram_instance(); // to load - return !( - ((flash_ram_instance.wallets[index].cards_states) >> (card_number - 1)) & - 1); + + bool wallet_found_on_card = IS_Ith_BIT_SET( + flash_ram_instance.wallets[index].cards_states, card_number - 1); + bool write_attempted_on_card = IS_Ith_BIT_SET( + flash_ram_instance.wallets[index].cards_states, card_number - 1 + 4); + + return !(wallet_found_on_card | write_attempted_on_card); } /** @@ -663,7 +724,7 @@ int set_wallet_locked(const char *wallet_name, uint8_t encoded_card_number) { flash_wallet->is_wallet_locked = true; memzero(&(flash_wallet->challenge), sizeof(flash_wallet->challenge)); flash_wallet->challenge.card_locked = encoded_card_number; - memset(flash_wallet->challenge.nonce, 0xFF, NONCE_SIZE); + memset(flash_wallet->challenge.nonce, 0xFF, PADDED_NONCE_SIZE); flash_struct_save(); return SUCCESS; } @@ -743,7 +804,7 @@ int update_wallet_locked_flash(const char *name, const bool is_wallet_locked) { flash_wallet->challenge.time_to_unlock_in_secs = 0; // Reset nonce to 0xFF as challenge is not fetched - memset(flash_wallet->challenge.nonce, 0xFF, NONCE_SIZE); + memset(flash_wallet->challenge.nonce, 0xFF, PADDED_NONCE_SIZE); } else { // Wallet unlocked, reset challenge memzero(&(flash_wallet->challenge), sizeof(flash_wallet->challenge)); diff --git a/common/interfaces/flash_interface/flash_api.h b/common/interfaces/flash_interface/flash_api.h index 6fc447891..ab135dc71 100644 --- a/common/interfaces/flash_interface/flash_api.h +++ b/common/interfaces/flash_interface/flash_api.h @@ -36,6 +36,17 @@ */ bool wallet_is_filled(uint8_t index, wallet_state *state_output); +/** + * @brief The function checks if a wallet is filled with a share based on its + * index. + * + * @param index The index required to be checked for wallet existance + * + * @return a boolean value. It returns true if the wallet at the given index is + * filled with a share, and false otherwise. + */ +bool wallet_is_filled_with_share(uint8_t index); + /** * Update auth state and first_boot_on_update variables in firewall */ @@ -64,6 +75,8 @@ int add_wallet_to_flash(const Flash_Wallet *wallet, uint32_t *index_OUT); * * @param[in] fwallet a constant reference to an object of type Flash_Wallet * @param[out] index_OUT index at which share entry is made + * @param[in] wallet_share The 5th share of wallet to be written on device + * @param[in] wallet_nonce Wallet nonce common for all shares * @return SUCCESS, MEMORY_OVERFLOW, INVALID_ARGUMENT, ALREADY_EXISTS * @retval SUCCESS Wallet share written to firewall region * @retval MEMORY_OVERFLOW in case of no empty slots @@ -72,8 +85,8 @@ int add_wallet_to_flash(const Flash_Wallet *wallet, uint32_t *index_OUT); */ int add_wallet_share_to_sec_flash(const Flash_Wallet *fwallet, uint32_t *index_OUT, - const uint8_t *wallet_share); - + const uint8_t *wallet_share, + const uint8_t *wallet_nonce); /** * @brief Deletes a wallet from flash * @@ -172,7 +185,9 @@ int put_wallet_flash(uint8_t index, const Flash_Wallet *wallet); * @retval INVALID_ARGUMENT non-existent wallet reference or wallet_index >= * MAX_WALLETS_ALLOWED */ -int put_wallet_share_sec_flash(uint8_t index, const uint8_t *wallet_share); +int put_wallet_share_sec_flash(uint8_t index, + const uint8_t *wallet_share, + const uint8_t *wallet_nonce); /** * @brief Outputs the index of the wallet with given name @@ -262,8 +277,23 @@ int get_flash_wallet_by_name(const char *name, Flash_Wallet **flash_wallet_OUT); int get_flash_wallet_share_by_name(const char *name, uint8_t *wallet_share); /** - * @brief Update the card states for the wallet at specified index (on deletion - * of the wallet from the given card number) + * Retrieves the wallet nonce associated with a given name from flash memory. + * + * @param name A pointer to a character array representing the name of the + * wallet. + * @param wallet_nonce A pointer to a uint8_t array where the wallet nonce will + * be stored. + * + * @return SUCCESS, INVALID_ARGUMENT, DOESNT_EXIST + * @retval SUCCESS Wallet found & wallet share returned + * @retval INVALID_ARGUMENT Passed name is invalid + * @retval DOESNT_EXIST Wallet does not exist with given name + */ +int get_flash_wallet_nonce_by_name(const char *name, uint8_t *wallet_nonce); + +/** + * @brief Update the card states(write and attempt states) for the wallet at + * specified index (on deletion of the wallet from the given card number) * * @param index Wallet index in flash * @param card_number Card number to delete @@ -275,6 +305,9 @@ int delete_from_kth_card_flash(uint8_t index, uint8_t card_number); * @brief Tells if the wallet at specified index is already deleted from the * given card number * + * @details This function checks the write state and attempt state of the wallet + * to be deleted. + * * @param index Wallet index in flash * @param card_number Card number to check * @return true, false diff --git a/common/interfaces/flash_interface/flash_struct.h b/common/interfaces/flash_interface/flash_struct.h index 004d28efd..2df514f0c 100644 --- a/common/interfaces/flash_interface/flash_struct.h +++ b/common/interfaces/flash_interface/flash_struct.h @@ -87,14 +87,17 @@ typedef struct Flash_Wallet { uint8_t wallet_name[NAME_SIZE]; uint8_t wallet_info; uint8_t - wallet_share_with_mac_and_nonce[BLOCK_SIZE + NONCE_SIZE + + wallet_share_with_mac_and_nonce[BLOCK_SIZE + PADDED_NONCE_SIZE + WALLET_MAC_SIZE]; // does not include // MAC and nonce uint8_t state; // if DEFAULT_VALUE_IN_FLASH then not valid. If equal to // VALID_WALLET then valid - uint8_t cards_states; // ith from right ((cards_states>>i)&1) bit tells - // whether card (i+1) has the share or not. + uint8_t cards_states; // ith bit from right ((cards_states>>i)&1) bit tells + // whether card (i+1) has the share or not. + // Attempt state is also recorded on the left nibble, + // recorded before card write operation is attempted + // and cleared when successful. uint8_t is_wallet_locked; // 1 if wallet if locked Flash_Pow challenge; } Flash_Wallet; diff --git a/common/libraries/util/utils.h b/common/libraries/util/utils.h index d90d59b8c..e742f249c 100644 --- a/common/libraries/util/utils.h +++ b/common/libraries/util/utils.h @@ -60,6 +60,10 @@ #define UTIL_OUT_OF_BOUNDS (0x22) #define UTIL_IN_BOUNDS (0xAA) +#define IS_Ith_BIT_SET(x, i) (((x) & (1 << (i))) != 0) +#define SET_Ith_BIT(x, i) ((x) |= (1 << (i))) +#define RESET_Ith_BIT(x, i) ((x) &= ~(1 << (i))) + /** * @brief Generic return codes for functions */ diff --git a/common/libraries/util/wallet_utilities.c b/common/libraries/util/wallet_utilities.c index fff26fe06..02e374de0 100644 --- a/common/libraries/util/wallet_utilities.c +++ b/common/libraries/util/wallet_utilities.c @@ -177,4 +177,19 @@ Card_Data_errors_t validate_wallet(Wallet *wallet) { if (is_zero(wallet->wallet_id, sizeof(wallet->wallet_id))) return INVALID_WALLET_ID; return VALID_DATA; +} + +void derive_wallet_nonce( + uint8_t share_encryption_data[TOTAL_NUMBER_OF_SHARES] + [PADDED_NONCE_SIZE + WALLET_MAC_SIZE]) { + uint8_t wallet_nonce[NONCE_SIZE] = {0}; + random_generate(wallet_nonce, NONCE_SIZE); + + for (int i = 0; i < TOTAL_NUMBER_OF_SHARES; i++) { + // First 12 bytes of share_encryption_data are wallet nonce. + memcpy(share_encryption_data[i], wallet_nonce, NONCE_SIZE); + // Skip next 3 bytes as RFU + // Version byte + share_encryption_data[i][15] = 0x01; + } } \ No newline at end of file diff --git a/common/libraries/util/wallet_utilities.h b/common/libraries/util/wallet_utilities.h index e00f35924..4b2e92717 100644 --- a/common/libraries/util/wallet_utilities.h +++ b/common/libraries/util/wallet_utilities.h @@ -113,4 +113,17 @@ void derive_wallet_key(uint8_t key[KEY_SIZE], const char *mnemonics); */ Card_Data_errors_t validate_wallet(Wallet *wallet); +/** + * @brief The function `derive_wallet_nonce` generates a random wallet nonce and + * assigns it to each share. On the share_encryption_data 2-D array, the wallet + * nonce is stored at the first 12 bytes and next 4 bytes contain RFU bytes + 1 + * version byte. + * + * @param share_encryption_data This 2-D array is used to store the share + * encryption data for each share. + */ +void derive_wallet_nonce( + uint8_t share_encryption_data[TOTAL_NUMBER_OF_SHARES] + [PADDED_NONCE_SIZE + WALLET_MAC_SIZE]); + #endif \ No newline at end of file diff --git a/src/card_flows/card_flow_delete_wallet.c b/src/card_flows/card_flow_delete_wallet.c index 487536d6f..a2c502432 100644 --- a/src/card_flows/card_flow_delete_wallet.c +++ b/src/card_flows/card_flow_delete_wallet.c @@ -59,11 +59,12 @@ /***************************************************************************** * INCLUDES *****************************************************************************/ +#include "buzzer.h" #include "card_operations.h" #include "constant_texts.h" +#include "core_error.h" #include "nfc.h" -#include "ui_instruction.h" - +#include "ui_screens.h" /***************************************************************************** * EXTERN VARIABLES *****************************************************************************/ @@ -101,6 +102,17 @@ static void check_card_state_and_delete_wallet(const char *wallet_name); static bool check_wallet_already_deleted_on_card( card_delete_share_cfg_t *delete_config); +/** + * The function `handle_wallet_deleted_from_card` deletes a wallet from a card. + * + * @param delete_config A pointer to a structure of type + * `card_delete_share_cfg_t`, which contains the following members: + * + * @return void, which means it does not return any value. + */ +static void handle_wallet_deleted_from_card( + card_delete_share_cfg_t *delete_config); + /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ @@ -119,6 +131,7 @@ static void check_card_state_and_delete_wallet(const char *wallet_name) { if (0 == get_wallet_card_state(flash_wallet_index)) { ASSERT(SUCCESS_ == delete_wallet_share_from_sec_flash(flash_wallet_index)); ASSERT(SUCCESS_ == delete_wallet_from_flash(flash_wallet_index)); + delay_scr_init(ui_text_wallet_deleted_successfully, DELAY_TIME); } return; } @@ -137,25 +150,86 @@ static bool check_wallet_already_deleted_on_card( return false; } +static void handle_wallet_deleted_from_card( + card_delete_share_cfg_t *delete_config) { + uint8_t flash_wallet_index = 0xFF; + + ASSERT(SUCCESS == + get_index_by_name((const char *)delete_config->wallet->wallet_name, + &flash_wallet_index)); + ASSERT(SUCCESS == delete_from_kth_card_flash(flash_wallet_index, + delete_config->card_number)); + return; +} + /***************************************************************************** * GLOBAL FUNCTIONS *****************************************************************************/ card_error_type_e card_flow_delete_wallet(Wallet *selected_wallet) { - card_delete_share_cfg_t cfg = {.wallet = selected_wallet, .card_number = 0}; + card_delete_share_cfg_t delete_cfg = {.wallet = selected_wallet, + .card_number = 0}; card_error_type_e error_code = 0; + card_fetch_share_config_t fetch_cfg = {0}; + card_fetch_share_response_t response = {0}; + char heading[MAX_HEADING_LEN] = ""; + fetch_cfg.xcor = 0; + fetch_cfg.operation.expected_family_id = get_family_id(); + fetch_cfg.frontend.msg = ui_text_place_card_below; + fetch_cfg.frontend.heading = heading; + fetch_cfg.frontend.unexpected_card_error = ui_text_wrong_card_sequence; + fetch_cfg.operation.skip_card_removal = true; + fetch_cfg.operation.buzzer_on_success = false; + response.card_info.tapped_family_id = NULL; + for (int i = 1; i <= 4; i++) { + snprintf(heading, MAX_HEADING_LEN, UI_TEXT_TAP_CARD, i); + fetch_cfg.operation.acceptable_cards = encode_card_number(i); + error_code = CARD_OPERATION_DEFAULT_INVALID; - cfg.card_number = i; + delete_cfg.card_number = i; // If wallet already deleted from ith card, skip card tapping - if (true == check_wallet_already_deleted_on_card(&cfg)) { + if (true == check_wallet_already_deleted_on_card(&delete_cfg)) { error_code = CARD_OPERATION_SUCCESS; continue; } + error_code = card_fetch_share(&fetch_cfg, &response); + + if (CARD_OPERATION_SUCCESS != error_code) { + if (CARD_OPERATION_ABORT_OPERATION == error_code && + SW_RECORD_NOT_FOUND == response.card_info.status) { + // In case wallet is not found on card, consider it as a success case as + // wallet is already deleted or not created on the card. + clear_core_error_screen(); + // Let it pass to wallet delete flow as the card operation will get + // completed there. + } else if (CARD_OPERATION_VERIFICATION_FAILED == error_code) { + // In case wallet verification fails, consider it as a success case + // wallet on card does not match with the required verification. + clear_core_error_screen(); + handle_wallet_deleted_from_card(&delete_cfg); + + // NOTE: When this case occurs, we are skipping card removal. This is + // because it is not possible to detect card's presence after desection. + // Card deselection is performed in fetch_card_share in this case. + buzzer_start(BUZZER_DURATION); + // TODO: Inform user that wallets with same name but failed verification + // might exist. + continue; + } else { + break; + } + } + + if (STM_SUCCESS != nfc_wait_for_card(DEFAULT_NFC_TG_INIT_TIME)) { + instruction_scr_change_text(ui_text_card_removed_fast, true); + } + // Operation to delete wallet from card and update card state on flash - error_code = card_delete_share(&cfg); + error_code = + card_delete_share(&delete_cfg, &handle_wallet_deleted_from_card); if (CARD_OPERATION_SUCCESS != error_code) { break; @@ -163,7 +237,8 @@ card_error_type_e card_flow_delete_wallet(Wallet *selected_wallet) { } // If wallet is deleted on all cards, delete from flash as well - check_card_state_and_delete_wallet((const char *)cfg.wallet->wallet_name); + check_card_state_and_delete_wallet( + (const char *)delete_cfg.wallet->wallet_name); return error_code; } \ No newline at end of file diff --git a/src/card_flows/card_flow_delete_wallet.h b/src/card_flows/card_flow_delete_wallet.h index 28ccbf92a..c28cfe670 100644 --- a/src/card_flows/card_flow_delete_wallet.h +++ b/src/card_flows/card_flow_delete_wallet.h @@ -33,8 +33,8 @@ * GLOBAL FUNCTION PROTOTYPES *****************************************************************************/ /** - * @brief This functions executes a sequential card flow to delete wallet on - * each of the 4 X1 cards + * @brief This functions executes a sequential card flow to fetch(for + * verification) and delete wallet on each of the 4 X1 cards * * @return true If the flow completed successfully and wallet share was written * and read back from all 4 cards diff --git a/src/card_flows/card_flow_reconstruct_wallet.c b/src/card_flows/card_flow_reconstruct_wallet.c index ecf8b6d4d..264ce1692 100644 --- a/src/card_flows/card_flow_reconstruct_wallet.c +++ b/src/card_flows/card_flow_reconstruct_wallet.c @@ -110,7 +110,9 @@ card_error_type_e card_flow_reconstruct_wallet(uint8_t threshold, configuration.operation.expected_family_id = get_family_id(); configuration.frontend.heading = ui_text_tap_1_2_cards; configuration.frontend.msg = ui_text_place_card_below; + configuration.frontend.unexpected_card_error = ui_text_tap_another_card; configuration.operation.skip_card_removal = false; + configuration.operation.buzzer_on_success = true; card_fetch_share_response_t response = {0}; response.card_info.tapped_family_id = NULL; diff --git a/src/card_operations/card_delete_share.c b/src/card_operations/card_delete_share.c index cb1a9be25..92da95cca 100644 --- a/src/card_operations/card_delete_share.c +++ b/src/card_operations/card_delete_share.c @@ -1,8 +1,7 @@ /** - * @file delete_from_cards_controller.c + * @file card_delete_share.c * @author Cypherock X1 Team - * @brief Delete from cards controller. - * This file contains the implementation of the functions for deleting + * @brief This file contains the implementation of the functions for deleting * wallets from cards. * @copyright Copyright (c) 2023 HODL TECH PTE LTD *
You may obtain a copy of license at wallet->wallet_name, - &flash_wallet_index)); - ASSERT(SUCCESS == delete_from_kth_card_flash(flash_wallet_index, - delete_config->card_number)); - return; -} /***************************************************************************** * GLOBAL FUNCTIONS *****************************************************************************/ -card_error_type_e card_delete_share(card_delete_share_cfg_t *delete_config) { +card_error_type_e card_delete_share( + card_delete_share_cfg_t *delete_config, + void (*handle_wallet_deleted_from_card)(card_delete_share_cfg_t *)) { card_operation_data_t card_data = {0}; card_error_type_e result = CARD_OPERATION_DEFAULT_INVALID; char heading[50] = ""; snprintf( heading, sizeof(heading), UI_TEXT_TAP_CARD, delete_config->card_number); - instruction_scr_init(ui_text_place_card_below, heading); - card_data.error_type = CARD_OPERATION_DEFAULT_INVALID; card_data.nfc_data.retries = 5; diff --git a/src/card_operations/card_delete_share.h b/src/card_operations/card_delete_share.h index 5e607b112..1a46638d1 100644 --- a/src/card_operations/card_delete_share.h +++ b/src/card_operations/card_delete_share.h @@ -44,8 +44,15 @@ typedef struct card_delete_share_cfg { * error cases and returns an appropriate error code. For special case such as * incorrect pin, it indicates the no. of attempts left. * - * @param config A pointer to the configuration of the card delete operation. + * @param delete_config A pointer to the configuration of the card delete + * operation. + * @param handle_wallet_deleted_from_card Function pointer that needs to be + * called to handle successful deletion of wallet on a card. The function takes + * the delete_config as an argument. + * * @return A card_error_type_e value representing the result of the operation. */ -card_error_type_e card_delete_share(card_delete_share_cfg_t *config); +card_error_type_e card_delete_share( + card_delete_share_cfg_t *delete_config, + void (*handle_wallet_deleted_from_card)(card_delete_share_cfg_t *)); #endif diff --git a/src/card_operations/card_fetch_share.c b/src/card_operations/card_fetch_share.c index 7c0d73fde..55f80034f 100644 --- a/src/card_operations/card_fetch_share.c +++ b/src/card_operations/card_fetch_share.c @@ -65,6 +65,7 @@ #include "card_internal.h" #include "card_utils.h" #include "constant_texts.h" +#include "core_error.h" #include "flash_api.h" #include "nfc.h" #include "ui_screens.h" @@ -85,13 +86,27 @@ extern Wallet_shamir_data wallet_shamir_data; /***************************************************************************** * STATIC FUNCTION PROTOTYPES *****************************************************************************/ +/** + * The function `verify_fetched_wallet` compares the values of a `wallet` object + * with the values of a `flash_wallet` object and returns a boolean indicating + * whether they are equal. + * + * @param xcor The x-coordinate of the wallet share, this variable represents + * the share index fetched from the last tapped card. + * + * @return a boolean value, which indicates whether the fetched wallet matches + * the expected values. + */ +static bool verify_fetched_wallet(uint8_t xcor); + /** * @brief Helper function that copies wallet share retrieved from X1 card onto * the RAM * - * @param xcor The x-coordinate of the wallet share + * @param xcor The x-coordinate of the wallet share, this variable represents + * the share index fetched from the last tapped card. */ -static void _handle_retrieve_wallet_success(uint8_t xcor); +static bool _handle_retrieve_wallet_success(uint8_t xcor); /***************************************************************************** * STATIC VARIABLES @@ -105,24 +120,76 @@ static uint8_t remaining_cards; /***************************************************************************** * STATIC FUNCTIONS *****************************************************************************/ -static void _handle_retrieve_wallet_success(uint8_t xcor) { - if (WALLET_IS_ARBITRARY_DATA(wallet.wallet_info)) + +static bool verify_fetched_wallet(uint8_t xcor) { + Flash_Wallet *flash_wallet = NULL; + bool status = + get_flash_wallet_by_name((const char *)wallet.wallet_name, &flash_wallet); + + ASSERT(SUCCESS == status && NULL != flash_wallet); + + bool compare_status = + (0 == memcmp(wallet.wallet_id, flash_wallet->wallet_id, WALLET_ID_SIZE)); + compare_status &= + (0 == memcmp(wallet.wallet_name, flash_wallet->wallet_name, NAME_SIZE)); + compare_status &= (wallet.wallet_info == flash_wallet->wallet_info); + + /** + * For wallets with device share present on flash, fetched wallet nonce is + * compared with wallet nonce on flash. In case of sync wallet, the wallet + * share and encryption data is written on flash after verification. For + * verifying the wallets in this case, we compare wallet nonce fetched from + * the two cards. + */ + if (VALID_WALLET_WITHOUT_DEVICE_SHARE != flash_wallet->state) { + // Wallet nonce present on flash, so compare current wallet nonce with flash + // wallet nonce. + uint8_t wallet_nonce[NONCE_SIZE] = {0}; + ASSERT(SUCCESS == + get_flash_wallet_nonce_by_name( + (const char *)flash_wallet->wallet_name, wallet_nonce)); + compare_status &= + (0 == memcmp(wallet.wallet_share_with_mac_and_nonce + BLOCK_SIZE, + wallet_nonce, + NONCE_SIZE)); + } else if (0 < xcor) { + // Compare nonce from current wallet with nonce of wallet previously + // fetched. + compare_status &= + (0 == memcmp(wallet.wallet_share_with_mac_and_nonce + BLOCK_SIZE, + wallet_shamir_data.share_encryption_data[xcor - 1], + NONCE_SIZE)); + } + return compare_status; +} + +static bool _handle_retrieve_wallet_success(uint8_t xcor) { + if (!verify_fetched_wallet(xcor)) { + LOG_ERROR("Verification failed xxx39"); + return false; + } + + if (WALLET_IS_ARBITRARY_DATA(wallet.wallet_info)) { memcpy(((uint8_t *)wallet_shamir_data.arbitrary_data_shares) + xcor * wallet.arbitrary_data_size, wallet.arbitrary_data_share, wallet.arbitrary_data_size); - else + } else { memcpy(wallet_shamir_data.mnemonic_shares[xcor], wallet.wallet_share_with_mac_and_nonce, BLOCK_SIZE); + } + memcpy(wallet_shamir_data.share_encryption_data[xcor], wallet.wallet_share_with_mac_and_nonce + BLOCK_SIZE, - NONCE_SIZE + WALLET_MAC_SIZE); + PADDED_NONCE_SIZE + WALLET_MAC_SIZE); memzero(wallet.arbitrary_data_share, sizeof(wallet.arbitrary_data_share)); memzero(wallet.wallet_share_with_mac_and_nonce, sizeof(wallet.wallet_share_with_mac_and_nonce)); wallet_shamir_data.share_x_coords[xcor] = wallet.xcor; + + return true; } /***************************************************************************** @@ -160,8 +227,17 @@ card_error_type_e card_fetch_share(const card_fetch_share_config_t *config, if (card_data.nfc_data.status == SW_NO_ERROR) { remaining_cards = card_data.nfc_data.acceptable_cards; - _handle_retrieve_wallet_success(config->xcor); - buzzer_start(BUZZER_DURATION); + if (!_handle_retrieve_wallet_success(config->xcor)) { + result = card_data.error_type = CARD_OPERATION_VERIFICATION_FAILED; + card_data.nfc_data.status = SW_RECORD_NOT_FOUND; + mark_core_error_screen( + ui_text_wallet_verification_failed_in_reconstruction, true); + break; + } + + if (config->operation.buzzer_on_success) { + buzzer_start(BUZZER_DURATION); + } if (false == config->operation.skip_card_removal) { wait_for_card_removal(); @@ -183,7 +259,7 @@ card_error_type_e card_fetch_share(const card_fetch_share_config_t *config, * sequence" */ if (SW_CONDITIONS_NOT_SATISFIED == card_data.nfc_data.status) { - error_msg = ui_text_tap_another_card; + error_msg = config->frontend.unexpected_card_error; } if (CARD_OPERATION_SUCCESS == indicate_card_error(error_msg)) { diff --git a/src/card_operations/card_operation_typedefs.h b/src/card_operations/card_operation_typedefs.h index 0db7d4611..56da849a2 100644 --- a/src/card_operations/card_operation_typedefs.h +++ b/src/card_operations/card_operation_typedefs.h @@ -38,6 +38,9 @@ typedef enum card_errors_type { CARD_OPERATION_RETAP_BY_USER_REQUIRED, /** Errors that occur due to user mistakes, like wrong card number or card of wrong family tapped */ + CARD_OPERATION_VERIFICATION_FAILED, /** Error occuring when wallet present on + card is different from the wallet + expected*/ CARD_OPERATION_ABORT_OPERATION, /** Error occurring due to internal handling of NFC or card communication. These errors can be associated to @ref @@ -51,11 +54,13 @@ typedef struct { uint8_t acceptable_cards; bool skip_card_removal; const uint8_t *expected_family_id; + bool buzzer_on_success; } card_operation_config_t; typedef struct { const char *heading; const char *msg; + const char *unexpected_card_error; } card_operation_frontend_t; typedef struct { diff --git a/src/card_operations/card_read_verify_shares.c b/src/card_operations/card_read_verify_shares.c index 727fe7a2d..efeec3b7d 100644 --- a/src/card_operations/card_read_verify_shares.c +++ b/src/card_operations/card_read_verify_shares.c @@ -117,7 +117,7 @@ static void read_card_share_post_process(uint8_t xcor) { BLOCK_SIZE); memcpy(wallet_shamir_data.share_encryption_data[xcor], wallet.wallet_share_with_mac_and_nonce + BLOCK_SIZE, - NONCE_SIZE + WALLET_MAC_SIZE); + PADDED_NONCE_SIZE + WALLET_MAC_SIZE); memzero(wallet.arbitrary_data_share, sizeof(wallet.arbitrary_data_share)); memzero(wallet.wallet_share_with_mac_and_nonce, sizeof(wallet.wallet_share_with_mac_and_nonce)); diff --git a/src/card_operations/card_write_share.c b/src/card_operations/card_write_share.c index 2568ad46c..aa96dca79 100644 --- a/src/card_operations/card_write_share.c +++ b/src/card_operations/card_write_share.c @@ -91,6 +91,15 @@ extern Wallet_shamir_data wallet_shamir_data; */ static void write_card_pre_process(uint8_t card_num); +/** + * @brief The function records a card write attempt on the flash memory and + * updates the state of the flash wallet accordingly. + * + * @param card_num represents the number of the card on which write operation is + * being attempted. + */ +static void record_card_write_attempt_on_flash(uint8_t card_num); + /** * @brief Handles post-processing required during the wallet share write * operation on the X1 card. @@ -124,20 +133,38 @@ static void write_card_pre_process(uint8_t card_num) { BLOCK_SIZE); memcpy(wallet.wallet_share_with_mac_and_nonce + BLOCK_SIZE, wallet_shamir_data.share_encryption_data[card_num - 1], - NONCE_SIZE + WALLET_MAC_SIZE); + PADDED_NONCE_SIZE + WALLET_MAC_SIZE); return; } -static void write_card_share_post_process(uint8_t card_num) { +static void record_card_write_attempt_on_flash(uint8_t card_num) { Flash_Wallet *wallet_for_flash = get_flash_wallet(); - wallet_for_flash->cards_states = (1 << card_num) - 1; + uint8_t attempt_card_state = encode_card_number(card_num) << 4; + + if (attempt_card_state == + (attempt_card_state & wallet_for_flash->cards_states)) { + // Attempt card state already recorded on flash, no need to write to flash + // again. Reached here probably due to retry attempt on same card. + return; + } + wallet_for_flash->cards_states |= attempt_card_state; if (card_num == 1) { wallet_for_flash->state = UNVERIFIED_VALID_WALLET; add_wallet_to_flash(wallet_for_flash, &wallet_index); } else { put_wallet_flash(wallet_index, wallet_for_flash); } + return; +} + +static void write_card_share_post_process(uint8_t card_num) { + Flash_Wallet *wallet_for_flash = get_flash_wallet(); + + wallet_for_flash->cards_states &= 0x0F; + wallet_for_flash->cards_states |= encode_card_number(card_num); + + put_wallet_flash(wallet_index, wallet_for_flash); if (WALLET_IS_ARBITRARY_DATA(wallet.wallet_info)) memset(((uint8_t *)wallet_shamir_data.arbitrary_data_shares) + @@ -153,6 +180,7 @@ static void write_card_share_post_process(uint8_t card_num) { (card_num - 1) * wallet.arbitrary_data_size, 0, wallet.arbitrary_data_size); + return; } /***************************************************************************** @@ -180,6 +208,7 @@ bool write_card_share(uint8_t card_num, const char *heading, const char *msg) { card_initialize_applet(&card_data); if (CARD_OPERATION_SUCCESS == card_data.error_type) { + record_card_write_attempt_on_flash(card_num); card_data.nfc_data.status = nfc_add_wallet(&wallet); if (card_data.nfc_data.status == SW_NO_ERROR) { diff --git a/src/constant_texts.c b/src/constant_texts.c index 63a5d3573..500b2503b 100644 --- a/src/constant_texts.c +++ b/src/constant_texts.c @@ -333,7 +333,7 @@ const char *ui_text_card_null_pointer_exception = const char *ui_text_card_crypto_exception = "Operation failed on card (Crypto Exp)"; const char *ui_text_card_invalid_apdu_length = - "Operation failed on card (APDU len exp)"; + "Wallet with same name or seed already exists"; const char *ui_text_card_invalid_tag_in_apdu = "Operation failed on card (Tag exp)"; const char *ui_text_unknown_error_contact_support = diff --git a/src/level_four/core/controller/receive_transaction_controller_eth.c b/src/level_four/core/controller/receive_transaction_controller_eth.c index da21f1a66..7049787fd 100644 --- a/src/level_four/core/controller/receive_transaction_controller_eth.c +++ b/src/level_four/core/controller/receive_transaction_controller_eth.c @@ -137,7 +137,7 @@ void receive_transaction_controller_eth() { wallet_shamir_data.mnemonic_shares[1]); memcpy(wallet_shamir_data.share_encryption_data[1], wallet_shamir_data.share_encryption_data[0], - NONCE_SIZE + WALLET_MAC_SIZE); + PADDED_NONCE_SIZE + WALLET_MAC_SIZE); flow_level.level_three = RECV_TXN_DERIVE_ADD_SCREEN_ETH; break; diff --git a/src/level_four/core/controller/receive_transaction_controller_near.c b/src/level_four/core/controller/receive_transaction_controller_near.c index a0918e46a..d657d358e 100644 --- a/src/level_four/core/controller/receive_transaction_controller_near.c +++ b/src/level_four/core/controller/receive_transaction_controller_near.c @@ -171,7 +171,7 @@ void receive_transaction_controller_near() { wallet_shamir_data.mnemonic_shares[1]); memcpy(wallet_shamir_data.share_encryption_data[1], wallet_shamir_data.share_encryption_data[0], - NONCE_SIZE + WALLET_MAC_SIZE); + PADDED_NONCE_SIZE + WALLET_MAC_SIZE); flow_level.level_three = RECV_TXN_DERIVE_ADD_SCREEN_NEAR; break; diff --git a/src/level_four/core/controller/receive_transaction_controller_solana.c b/src/level_four/core/controller/receive_transaction_controller_solana.c index 040883dba..397c5b16e 100644 --- a/src/level_four/core/controller/receive_transaction_controller_solana.c +++ b/src/level_four/core/controller/receive_transaction_controller_solana.c @@ -133,7 +133,7 @@ void receive_transaction_controller_solana() { wallet_shamir_data.mnemonic_shares[1]); memcpy(wallet_shamir_data.share_encryption_data[1], wallet_shamir_data.share_encryption_data[0], - NONCE_SIZE + WALLET_MAC_SIZE); + PADDED_NONCE_SIZE + WALLET_MAC_SIZE); flow_level.level_three = RECV_TXN_DERIVE_ADD_SCREEN_SOLANA; break; diff --git a/src/level_four/core/controller/send_transaction_controller_eth.c b/src/level_four/core/controller/send_transaction_controller_eth.c index 49d300d97..9af38ae6b 100644 --- a/src/level_four/core/controller/send_transaction_controller_eth.c +++ b/src/level_four/core/controller/send_transaction_controller_eth.c @@ -214,7 +214,7 @@ void send_transaction_controller_eth() { wallet_shamir_data.mnemonic_shares[1]); memcpy(wallet_shamir_data.share_encryption_data[1], wallet_shamir_data.share_encryption_data[0], - NONCE_SIZE + WALLET_MAC_SIZE); + PADDED_NONCE_SIZE + WALLET_MAC_SIZE); flow_level.level_three = SEND_TXN_SIGN_TXN_ETH; break; diff --git a/src/level_four/core/controller/send_transaction_controller_solana.c b/src/level_four/core/controller/send_transaction_controller_solana.c index 41dee9d29..66b932b20 100644 --- a/src/level_four/core/controller/send_transaction_controller_solana.c +++ b/src/level_four/core/controller/send_transaction_controller_solana.c @@ -230,7 +230,7 @@ void send_transaction_controller_solana() { wallet_shamir_data.mnemonic_shares[1]); memcpy(wallet_shamir_data.share_encryption_data[1], wallet_shamir_data.share_encryption_data[0], - NONCE_SIZE + WALLET_MAC_SIZE); + PADDED_NONCE_SIZE + WALLET_MAC_SIZE); flow_level.level_three = SEND_TXN_SIGN_TXN_SOLANA; break; diff --git a/src/level_four/core/controller/sign_message_controller_eth.c b/src/level_four/core/controller/sign_message_controller_eth.c index 957c4f784..73f1ffe57 100644 --- a/src/level_four/core/controller/sign_message_controller_eth.c +++ b/src/level_four/core/controller/sign_message_controller_eth.c @@ -176,7 +176,7 @@ void sign_message_controller_eth() { wallet_shamir_data.mnemonic_shares[1]); memcpy(wallet_shamir_data.share_encryption_data[1], wallet_shamir_data.share_encryption_data[0], - NONCE_SIZE + WALLET_MAC_SIZE); + PADDED_NONCE_SIZE + WALLET_MAC_SIZE); flow_level.level_three = SIGN_MSG_SIGN_TXN_ETH; break; diff --git a/src/settings/factory_reset.c b/src/settings/factory_reset.c index 10e978f3d..ac2158e25 100644 --- a/src/settings/factory_reset.c +++ b/src/settings/factory_reset.c @@ -294,7 +294,7 @@ static bool safe_to_delete_wallet_share(wallet_list_t *wallets_in_vault) { *****************************************************************************/ void factory_reset(void) { wallet_list_t wallets_in_vault = {0}; - uint8_t valid_wallets = get_valid_wallet_meta_data_list(&wallets_in_vault); + uint8_t valid_wallets = get_filled_wallet_meta_data_list(&wallets_in_vault); if (0 < valid_wallets && !core_scroll_page(NULL, ui_text_factory_reset_instruction, NULL)) { @@ -329,7 +329,7 @@ void factory_reset(void) { void clear_device_data(void) { wallet_list_t wallets_in_vault = {0}; - uint8_t valid_wallets = get_valid_wallet_meta_data_list(&wallets_in_vault); + uint8_t valid_wallets = get_filled_wallet_meta_data_list(&wallets_in_vault); if (0 < valid_wallets && !core_scroll_page(NULL, ui_text_clear_device_data_instruction, NULL)) { diff --git a/src/wallet/create_new_wallet_flow.c b/src/wallet/create_new_wallet_flow.c index fa05c0b87..4ab507818 100644 --- a/src/wallet/create_new_wallet_flow.c +++ b/src/wallet/create_new_wallet_flow.c @@ -326,8 +326,12 @@ new_wallet_state_e new_wallet_state_handler(new_wallet_state_e current_state) { wallet.total_number_of_shares, wallet.minimum_number_of_shares, wallet_shamir_data.mnemonic_shares); - if (WALLET_IS_PIN_SET(wallet.wallet_info)) + + derive_wallet_nonce(wallet_shamir_data.share_encryption_data); + + if (WALLET_IS_PIN_SET(wallet.wallet_info)) { encrypt_shares(); + } derive_beneficiary_key( wallet.beneficiary_key, wallet.iv_for_beneficiary_key, mnemo); derive_wallet_key(wallet.key, mnemo); @@ -343,7 +347,10 @@ new_wallet_state_e new_wallet_state_handler(new_wallet_state_e current_state) { uint32_t index; wallet_for_flash.state = DEFAULT_VALUE_IN_FLASH; add_wallet_share_to_sec_flash( - &wallet_for_flash, &index, wallet_shamir_data.mnemonic_shares[4]); + &wallet_for_flash, + &index, + wallet_shamir_data.mnemonic_shares[4], + wallet_shamir_data.share_encryption_data[4]); next_state = TAP_CARD_FLOW; break; } diff --git a/src/wallet/reconstruct_wallet_flow.c b/src/wallet/reconstruct_wallet_flow.c index 86cc28455..87f23f605 100644 --- a/src/wallet/reconstruct_wallet_flow.c +++ b/src/wallet/reconstruct_wallet_flow.c @@ -282,7 +282,7 @@ static reconstruct_state_e reconstruct_wallet_handler(reconstruct_state_e state, wallet_shamir_data.mnemonic_shares[1]); memcpy(wallet_shamir_data.share_encryption_data[1], wallet_shamir_data.share_encryption_data[0], - NONCE_SIZE + WALLET_MAC_SIZE); + PADDED_NONCE_SIZE + WALLET_MAC_SIZE); if (WALLET_IS_PIN_SET(wallet.wallet_info)) { decrypt_shares(); diff --git a/src/wallet/restore_seed_phrase_flow.c b/src/wallet/restore_seed_phrase_flow.c index 5903c6624..8394b2d93 100644 --- a/src/wallet/restore_seed_phrase_flow.c +++ b/src/wallet/restore_seed_phrase_flow.c @@ -427,8 +427,12 @@ restore_wallet_state_e restore_wallet_state_handler( wallet.minimum_number_of_shares, wallet_shamir_data.mnemonic_shares); memzero(secret, sizeof(secret)); - if (WALLET_IS_PIN_SET(wallet.wallet_info)) + + derive_wallet_nonce(wallet_shamir_data.share_encryption_data); + + if (WALLET_IS_PIN_SET(wallet.wallet_info)) { encrypt_shares(); + } derive_beneficiary_key(wallet.beneficiary_key, wallet.iv_for_beneficiary_key, single_line_mnemonics); @@ -458,7 +462,10 @@ restore_wallet_state_e restore_wallet_state_handler( uint32_t index; wallet_for_flash.state = DEFAULT_VALUE_IN_FLASH; add_wallet_share_to_sec_flash( - &wallet_for_flash, &index, wallet_shamir_data.mnemonic_shares[4]); + &wallet_for_flash, + &index, + wallet_shamir_data.mnemonic_shares[4], + wallet_shamir_data.share_encryption_data[4]); next_state = TAP_CARD_FLOW; break; } diff --git a/src/wallet/sync_wallets_flow.c b/src/wallet/sync_wallets_flow.c index 3b939619a..857e873c2 100644 --- a/src/wallet/sync_wallets_flow.c +++ b/src/wallet/sync_wallets_flow.c @@ -164,7 +164,13 @@ static sync_state_e sync_wallet_handler(sync_state_e state) { case SYNC_RECONSTRUCT_SEED: { delay_scr_init(ui_text_processing, DELAY_TIME); - uint8_t temp_password_hash[SHA256_DIGEST_LENGTH]; + uint8_t temp_password_hash[SHA256_DIGEST_LENGTH] = {0}; + uint8_t wallet_nonce[PADDED_NONCE_SIZE] = {0}; + + memcpy(wallet_nonce, + wallet_shamir_data.share_encryption_data[0], + PADDED_NONCE_SIZE); + if (WALLET_IS_PIN_SET(wallet.wallet_info)) { memcpy(temp_password_hash, wallet_credential_data.password_single_hash, @@ -181,8 +187,8 @@ static sync_state_e sync_wallet_handler(sync_state_e state) { if (WALLET_IS_PIN_SET(wallet.wallet_info)) { memcpy(wallet_shamir_data.share_encryption_data[4], - wallet_shamir_data.share_encryption_data[0], - NONCE_SIZE + WALLET_MAC_SIZE); + wallet_nonce, + PADDED_NONCE_SIZE); memcpy(wallet_credential_data.password_single_hash, temp_password_hash, SHA256_DIGEST_LENGTH); @@ -198,8 +204,8 @@ static sync_state_e sync_wallet_handler(sync_state_e state) { (uint8_t *)(&wallet_index)); get_flash_wallet_by_name((const char *)wallet.wallet_name, &flash_wallet); memcpy(&wallet_for_flash, flash_wallet, sizeof(Flash_Wallet)); - put_wallet_share_sec_flash(wallet_index, - wallet_shamir_data.mnemonic_shares[4]); + put_wallet_share_sec_flash( + wallet_index, wallet_shamir_data.mnemonic_shares[4], wallet_nonce); next_state = SYNC_COMPLETED; break; diff --git a/src/wallet/wallet_list.c b/src/wallet/wallet_list.c index f87e31ab8..0a7237637 100644 --- a/src/wallet/wallet_list.c +++ b/src/wallet/wallet_list.c @@ -118,15 +118,14 @@ uint8_t get_wallet_list(const char *wallet_list[]) { return num_wallets; } -uint8_t get_valid_wallet_meta_data_list(wallet_list_t *list) { +uint8_t get_filled_wallet_meta_data_list(wallet_list_t *list) { uint8_t count = 0; if (NULL == list) { return count; } for (uint8_t wallet_idx = 0; wallet_idx < MAX_WALLETS_ALLOWED; wallet_idx++) { - wallet_state state = INVALID_WALLET; - if (!wallet_is_filled(wallet_idx, &state) || VALID_WALLET != state) { + if (!wallet_is_filled_with_share(wallet_idx)) { continue; } diff --git a/src/wallet/wallet_list.h b/src/wallet/wallet_list.h index 030fb69a9..e72442770 100644 --- a/src/wallet/wallet_list.h +++ b/src/wallet/wallet_list.h @@ -58,12 +58,12 @@ uint8_t get_wallet_list(const char *wallet_list[]); /** * @brief This API fills metadata for all the wallets present on X1 vault and - * are in VALID_WALLET state. + * are not in VALID_WALLET_WITHOUT_DEVICE_SHARE state. * * @param wallet_list Refernce to buffer which will be filled by this function * @return uint8_t The number of wallets returned */ -uint8_t get_valid_wallet_meta_data_list(wallet_list_t *wallet_list); +uint8_t get_filled_wallet_meta_data_list(wallet_list_t *wallet_list); /** * @brief This API searches for wallet on the flash using wallet_id as key and diff --git a/src/wallet/wallet_unlock_flow.c b/src/wallet/wallet_unlock_flow.c index 0f1aa8db9..cde43ae10 100644 --- a/src/wallet/wallet_unlock_flow.c +++ b/src/wallet/wallet_unlock_flow.c @@ -149,7 +149,7 @@ static wallet_unlock_state_e wallet_unlock_handler( *****************************************************************************/ static bool check_default_nonce(const uint8_t *nonce) { - for (size_t i = 0; i < NONCE_SIZE; i++) { + for (size_t i = 0; i < PADDED_NONCE_SIZE; i++) { if (nonce[i] != DEFAULT_VALUE_IN_FLASH) { return false; }