From 2927d175638c0496436a5c234bc2aa9359301d38 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 6 Mar 2025 07:27:55 +0530 Subject: [PATCH 01/75] feat: Added boilerpate code for constellation app --- apps/constellation_app/constellation_api.c | 196 ++++++++++++++++++ apps/constellation_app/constellation_api.h | 113 ++++++++++ .../constellation_app/constellation_context.h | 48 +++++ .../constellation_app/constellation_helpers.c | 114 ++++++++++ .../constellation_app/constellation_helpers.h | 52 +++++ apps/constellation_app/constellation_main.c | 149 +++++++++++++ apps/constellation_app/constellation_main.h | 43 ++++ apps/constellation_app/constellation_priv.h | 52 +++++ common/core/app_registry.h | 2 +- common/core/core_flow_init.c | 2 + common/cypherock-common | 2 +- .../proto-options/constellation/core.options | 1 + .../proto-options/constellation/error.options | 1 + utilities/cmake/firmware/firmware.cmake | 5 +- utilities/cmake/simulator/simulator.cmake | 2 + 15 files changed, 778 insertions(+), 4 deletions(-) create mode 100644 apps/constellation_app/constellation_api.c create mode 100644 apps/constellation_app/constellation_api.h create mode 100644 apps/constellation_app/constellation_context.h create mode 100644 apps/constellation_app/constellation_helpers.c create mode 100644 apps/constellation_app/constellation_helpers.h create mode 100644 apps/constellation_app/constellation_main.c create mode 100644 apps/constellation_app/constellation_main.h create mode 100644 apps/constellation_app/constellation_priv.h create mode 100644 common/proto-options/constellation/core.options create mode 100644 common/proto-options/constellation/error.options diff --git a/apps/constellation_app/constellation_api.c b/apps/constellation_app/constellation_api.c new file mode 100644 index 000000000..0204f6d79 --- /dev/null +++ b/apps/constellation_app/constellation_api.c @@ -0,0 +1,196 @@ +/** + * @file constellation_api.c + * @author Cypherock X1 Team + * @brief Defines helpers apis for CONSTELLATION app. + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2025 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "constellation_api.h" + +#include +#include + +#include "common_error.h" +#include "core_api.h" +#include "events.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ +bool decode_constellation_query(const uint8_t *data, + uint16_t data_size, + constellation_query_t *query_out) { + if (NULL == data || NULL == query_out || 0 == data_size) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + } + + // zeroise for safety from garbage in the query reference + memzero(query_out, sizeof(constellation_query_t)); + + /* Create a stream that reads from the buffer. */ + pb_istream_t stream = pb_istream_from_buffer(data, data_size); + + /* Now we are ready to decode the message. */ + bool status = pb_decode(&stream, CONSTELLATION_QUERY_FIELDS, query_out); + + /* Send error to host if status is false*/ + if (false == status) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + } + + return status; +} + +bool encode_constellation_result(const constellation_result_t *result, + uint8_t *buffer, + uint16_t max_buffer_len, + size_t *bytes_written_out) { + if (NULL == result || NULL == buffer || NULL == bytes_written_out) + return false; + + /* Create a stream that will write to our buffer. */ + pb_ostream_t stream = pb_ostream_from_buffer(buffer, max_buffer_len); + + /* Now we are ready to encode the message! */ + bool status = pb_encode(&stream, CONSTELLATION_RESULT_FIELDS, result); + + if (true == status) { + *bytes_written_out = stream.bytes_written; + } + + return status; +} + +bool check_constellation_query(const constellation_query_t *query, pb_size_t exp_query_tag) { + if ((NULL == query) || (exp_query_tag != query->which_request)) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_QUERY); + return false; + } + return true; +} + +constellation_result_t init_constellation_result(pb_size_t result_tag) { + constellation_result_t result = CONSTELLATION_RESULT_INIT_ZERO; + result.which_response = result_tag; + return result; +} + +void constellation_send_error(pb_size_t which_error, uint32_t error_code) { + constellation_result_t result = init_constellation_result(CONSTELLATION_RESULT_COMMON_ERROR_TAG); + result.common_error = init_common_error(which_error, error_code); + constellation_send_result(&result); +} + +void constellation_send_result(const constellation_result_t *result) { + // TODO: Set all option files + uint8_t buffer[1700] = {0}; + size_t bytes_encoded = 0; + ASSERT(encode_constellation_result(result, buffer, sizeof(buffer), &bytes_encoded)); + send_response_to_host(&buffer[0], bytes_encoded); +} + +bool constellation_get_query(constellation_query_t *query, pb_size_t exp_query_tag) { + evt_status_t event = get_events(EVENT_CONFIG_USB, MAX_INACTIVITY_TIMEOUT); + + if (true == event.p0_event.flag) { + return false; + } + + if (!decode_constellation_query( + event.usb_event.p_msg, event.usb_event.msg_size, query)) { + return false; + } + + if (!check_constellation_query(query, exp_query_tag)) { + return false; + } + + return true; +} diff --git a/apps/constellation_app/constellation_api.h b/apps/constellation_app/constellation_api.h new file mode 100644 index 000000000..7e6fb467c --- /dev/null +++ b/apps/constellation_app/constellation_api.h @@ -0,0 +1,113 @@ +/** + * @file constellation_api.h + * @author Cypherock X1 Team + * @brief Header file to export some helper functions for the CONSTELLATION app + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef CONSTELLATION_API_H +#define CONSTELLATION_API_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include + +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief API to decode query from host with `CONSTELLATION_QUERY_FIELDS` + * + * @param[in] data: PB encoded bytestream received from host + * @param[in] data_size: size of pb encoded bytestream + * @param[out] query_out: @ref constellation_query_t obj to copy the decoded result to + * @return bool True if decoding was successful, else false + */ +bool decode_constellation_query(const uint8_t *data, + uint16_t data_size, + constellation_query_t *query_out); + +/** + * @brief Encodes the CONSTELLATION result with `CONSTELLATION_RESULT_FIELDS` to byte-stream + * + * @param[in] result: object of populated @ref constellation_result_t to be encoded + * @param[out] buffer: buffer to fill byte-stream into + * @param[in] max_buffer_len: Max length allowed for writing bytestream to + * buffer + * @param[out] bytes_written_out: bytes written to bytestream + * @return bool True if decoding was successful, else false + */ +bool encode_constellation_result(const constellation_result_t *result, + uint8_t *buffer, + uint16_t max_buffer_len, + size_t *bytes_written_out); + +/** + * @brief This API checks if the `which_request` field of the query of type + * `constellation_query_t` matches against the expected tag. + * + * @param query The query of type `constellation_query_t` to be checked + * @param exp_query_tag The expected tag of the query + * @return true If the query tag matches the expected tag + * @return false If the query tag does not match the expected tag + */ +bool check_constellation_query(const constellation_query_t *query, pb_size_t exp_query_tag); + +/** + * @brief Returns zero initialized object of type + * constellation_result_t result_tag set in result.which_response field + * + * @param result_tag Result tag to be set in the constellation_result_t result + * @return constellation_result_t Result object of type constellation_result_t + */ +constellation_result_t init_constellation_result(pb_size_t result_tag); + +/** + * @brief Send the error to the host. + * + * @param which_error The error type to be sent + * @param error_code The error code to sent to the host + */ +void constellation_send_error(pb_size_t which_error, uint32_t error_code); + +/** + * @brief This API encodes constellation_result_t in protobuf structure. + * @details If the encoding is successful, then it sends the corresponding + * result to the host. + * + * The function ASSERTs the result of encode_constellation_result internally. + * + * @param result The result which needs to be sent to the host. + */ +void constellation_send_result(const constellation_result_t *result); + +/** + * @brief This API receives request of type constellation_query_t of type + * exp_query_tag from the host. + * + * @param query The reference to which the query needs to be populated + * @param exp_query_tag The expected tag of the query + * @return true If the query was recieved from the host matching the tag + * @return false If the request timed out or the recieved request did not match + * the tag + */ +bool constellation_get_query(constellation_query_t *query, pb_size_t exp_query_tag); + +#endif diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h new file mode 100644 index 000000000..b21e5afeb --- /dev/null +++ b/apps/constellation_app/constellation_context.h @@ -0,0 +1,48 @@ +/** + * @file constellation_context.h + * @author Cypherock X1 Team + * @brief Header file defining typedefs and MACROS for the CONSTELLATION app + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef CONSTELLATION_CONTEXT_H +#define CONSTELLATION_CONTEXT_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ +#include +#include + +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ +#define CONSTELLATION_NAME "CONSTELLATION" +#define CONSTELLATION_LUNIT "DAG" + +#define CONSTELLATION_IMPLICIT_ACCOUNT_DEPTH 5 + +#define CONSTELLATION_PURPOSE_INDEX 0x8000002C // 44' +#define CONSTELLATION_COIN_INDEX 0x80000000 + 1137 // 1137' +#define CONSTELLATION_ACCOUNT_INDEX 0x80000000 // 0' +#define CONSTELLATION_CHANGE_INDEX 0x00000000 // 0 + + +#define CONSTELLATION_PUB_KEY_SIZE 33 +#define CONSTELLATION_UNCOMPRESSED_PUB_KEY_SIZE 65 +#define CONSTELLATION_ACCOUNT_ADDRESS_LENGTH 40 + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +#endif /* CONSTELLATION_CONTEXT_H */ \ No newline at end of file diff --git a/apps/constellation_app/constellation_helpers.c b/apps/constellation_app/constellation_helpers.c new file mode 100644 index 000000000..85a4efc3a --- /dev/null +++ b/apps/constellation_app/constellation_helpers.c @@ -0,0 +1,114 @@ +/** + * @file constellation_helpers.c + * @author Cypherock X1 Team + * @brief Utilities specific to Constellation chains + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2024 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "constellation_helpers.h" +#include "constellation_context.h" +#include "coin_utils.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +bool constellation_derivation_path_guard(const uint32_t *path, uint8_t levels) { + bool status = false; + if (levels != CONSTELLATION_IMPLICIT_ACCOUNT_DEPTH) { + return status; + } + + uint32_t purpose = path[0], coin = path[1], account = path[2], + change = path[3], address = path[4]; + + // m/44'/144'/0'/0/i + status = (CONSTELLATION_PURPOSE_INDEX == purpose && CONSTELLATION_COIN_INDEX == coin && + CONSTELLATION_ACCOUNT_INDEX == account && CONSTELLATION_CHANGE_INDEX == change && + is_non_hardened(address)); + + return status; +} diff --git a/apps/constellation_app/constellation_helpers.h b/apps/constellation_app/constellation_helpers.h new file mode 100644 index 000000000..ef9ff911f --- /dev/null +++ b/apps/constellation_app/constellation_helpers.h @@ -0,0 +1,52 @@ +/** + * @file constellation_helpers.h + * @author Cypherock X1 Team + * @brief Utilities api definitions for CONSTELLATION chains + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef CONSTELLATION_HELPERS_H +#define CONSTELLATION_HELPERS_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include +#include + +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Verifies the derivation path. + * @details The derivation depth is fixed at level 5. So if the depth level != + * 5, then this function return false indicating invalid derivation path. The + * function supports checking derivation paths for HD wallets Types of + * derivations: address: m/44'/144'/0'/0/i + * + * @param[in] path The derivation path as an uint32 array + * @param[in] levels The number of levels in the derivation path + * + * @return bool Indicates if the provided derivation path is valid + * @retval true if the derivation path is valid + * @retval false otherwise + */ +bool constellation_derivation_path_guard(const uint32_t *path, uint8_t levels); + +#endif // CONSTELLATION_HELPERS_H \ No newline at end of file diff --git a/apps/constellation_app/constellation_main.c b/apps/constellation_app/constellation_main.c new file mode 100644 index 000000000..458b7db3c --- /dev/null +++ b/apps/constellation_app/constellation_main.c @@ -0,0 +1,149 @@ +/** + * @file constellation_main.c + * @author Cypherock X1 Team + * @brief A common entry point to various CONSTELLATION coin actions supported. + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2024 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "constellation_main.h" + +#include "status_api.h" +#include "constellation_api.h" +#include "constellation_priv.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ +/** + * @brief Entry point for the CONSTELLATION application of the X1 vault. It is invoked + * by the X1 vault firmware, as soon as there is a USB request raised for the + * Constellation app. + * + * @param usb_evt The USB event which triggered invocation of the constellation app + */ +void constellation_main(usb_event_t usb_evt, const void *constellation_app_config); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +static const cy_app_desc_t constellation_app_desc = {.id = 23, + .version = + { + .major = 1, + .minor = 0, + .patch = 0, + }, + .app = constellation_main, + .app_config = NULL}; + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ +void constellation_main(usb_event_t usb_evt, const void *constellation_app_config) { + constellation_query_t query = CONSTELLATION_QUERY_INIT_DEFAULT; + + if (false == decode_constellation_query(usb_evt.p_msg, usb_evt.msg_size, &query)) { + return; + } + + /* Set status to CORE_DEVICE_IDLE_STATE_USB to indicate host that we are now + * servicing a USB initiated command */ + core_status_set_idle_state(CORE_DEVICE_IDLE_STATE_USB); + + switch ((uint8_t)query.which_request) { + case CONSTELLATION_QUERY_GET_PUBLIC_KEYS_TAG: + case CONSTELLATION_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG: { + constellation_get_pub_keys(&query); + break; + } + case CONSTELLATION_QUERY_SIGN_TXN_TAG: { + constellation_sign_transaction(&query); + break; + } + default: { + /* In case we ever encounter invalid query, convey to the host app */ + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_QUERY); + break; + } + } +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ +const cy_app_desc_t *get_constellation_app_desc() { + return &constellation_app_desc; +} \ No newline at end of file diff --git a/apps/constellation_app/constellation_main.h b/apps/constellation_app/constellation_main.h new file mode 100644 index 000000000..9dbaa2461 --- /dev/null +++ b/apps/constellation_app/constellation_main.h @@ -0,0 +1,43 @@ +/** + * @file constellation_main.h + * @author Cypherock X1 Team + * @brief + * @details + + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + */ + +#ifndef CONSTELLATION_MAIN_H +#define CONSTELLATION_MAIN_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "app_registry.h" +#include "events.h" +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ +/** + * @brief Returns the config for CONSTELLATION chain app descriptor + * + * @return A const reference to cy_app_desc_t + */ +const cy_app_desc_t *get_constellation_app_desc(); +#endif /* CONSTELLATION_MAIN_H */ diff --git a/apps/constellation_app/constellation_priv.h b/apps/constellation_app/constellation_priv.h new file mode 100644 index 000000000..676305a27 --- /dev/null +++ b/apps/constellation_app/constellation_priv.h @@ -0,0 +1,52 @@ +/** + * @file constellation_priv.h + * @author Cypherock X1 Team + * @brief Support for constellation app internal operations + * This file is defined to separate CONSTELLATION's internal use + * functions, flows, common APIs + * @copyright Copyright (c) 2024 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef CONSTELLATION_PRIV_H +#define CONSTELLATION_PRIV_H +/***************************************************************************** + * INCLUDES + *****************************************************************************/ +#include +#include + +#include "constellation_context.h" + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Handler for CONSTELLATION public key derivation. + * @details This flow expects CONSTELLATION_GET_PUBLIC_KEY_REQUEST_INITIATE_TAG as initial + * query, otherwise the flow is aborted + * + * @param query object for address public key query + */ +void constellation_get_pub_keys(constellation_query_t *query); + +/** + * @brief Handler for signing a transaction on constellation. + * @details The expected request type is CONSTELLATION_SIGN_TXN_REQUEST_INITIATE_TAG. The + * function controls the complete data exchange with host, user prompts and + * confirmations for signing an CONSTELLATION based transaction. + * + * @param query Reference to the decoded query struct from the host app + */ +void constellation_sign_transaction(constellation_query_t *query); + +#endif /* CONSTELLATION_PRIV_H */ \ No newline at end of file diff --git a/common/core/app_registry.h b/common/core/app_registry.h index 243f05b21..09951e5b4 100644 --- a/common/core/app_registry.h +++ b/common/core/app_registry.h @@ -23,7 +23,7 @@ * MACROS AND DEFINES *****************************************************************************/ -#define REGISTRY_MAX_APPS 22 +#define REGISTRY_MAX_APPS 24 /***************************************************************************** * TYPEDEFS diff --git a/common/core/core_flow_init.c b/common/core/core_flow_init.c index 1faddf4f6..ced16989f 100644 --- a/common/core/core_flow_init.c +++ b/common/core/core_flow_init.c @@ -68,6 +68,7 @@ #include "bsc_app.h" #include "btc_app.h" #include "btc_main.h" +#include "constellation_main.h" #include "dash_app.h" #include "doge_app.h" #include "eth_app.h" @@ -185,4 +186,5 @@ void core_init_app_registry() { registry_add_app(get_inheritance_app_desc()); registry_add_app(get_xrp_app_desc()); registry_add_app(get_starknet_app_desc()); + registry_add_app(get_constellation_app_desc()); } diff --git a/common/cypherock-common b/common/cypherock-common index 4b5ee9d84..60bf878b5 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit 4b5ee9d840b5eb512b38c03167c06fc65d81041c +Subproject commit 60bf878b5863e17c1a8b82a7972a45dd75892a7b diff --git a/common/proto-options/constellation/core.options b/common/proto-options/constellation/core.options new file mode 100644 index 000000000..7c4863400 --- /dev/null +++ b/common/proto-options/constellation/core.options @@ -0,0 +1 @@ +# Options for file common/cypherock-common/proto/xrp/core.proto diff --git a/common/proto-options/constellation/error.options b/common/proto-options/constellation/error.options new file mode 100644 index 000000000..5847b57ec --- /dev/null +++ b/common/proto-options/constellation/error.options @@ -0,0 +1 @@ +# Options for file common/cypherock-common/proto/xrp/error.proto diff --git a/utilities/cmake/firmware/firmware.cmake b/utilities/cmake/firmware/firmware.cmake index f0b8a837d..769d73ad9 100644 --- a/utilities/cmake/firmware/firmware.cmake +++ b/utilities/cmake/firmware/firmware.cmake @@ -60,9 +60,9 @@ target_include_directories(${EXECUTABLE} PRIVATE apps/tron_app apps/inheritance_app apps/starknet_app - apps/xrp_app - + apps/constellation_app + src/ src/menu src/wallet @@ -188,6 +188,7 @@ target_include_directories(${EXECUTABLE} PRIVATE $<$:${PROJECT_SOURCE_DIR}/tests/apps/solana_app> $<$:${PROJECT_SOURCE_DIR}/tests/apps/inheritance_app> $<$:${PROJECT_SOURCE_DIR}/tests/apps/xrp_app> + $<$:${PROJECT_SOURCE_DIR}/tests/apps/constellation_app> ) target_compile_options(${EXECUTABLE} PRIVATE diff --git a/utilities/cmake/simulator/simulator.cmake b/utilities/cmake/simulator/simulator.cmake index 21d5fa8c4..b4121d659 100644 --- a/utilities/cmake/simulator/simulator.cmake +++ b/utilities/cmake/simulator/simulator.cmake @@ -58,6 +58,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE apps/inheritance_app apps/xrp_app apps/starknet_app + apps/constellation_app src/ src/menu @@ -163,6 +164,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE $<$:${PROJECT_SOURCE_DIR}/tests/apps/solana_app> $<$:${PROJECT_SOURCE_DIR}/tests/apps/inheritance_app> $<$:${PROJECT_SOURCE_DIR}/tests/apps/xrp_app> + $<$:${PROJECT_SOURCE_DIR}/tests/apps/constellation_app> ) IF(UNIT_TESTS_SWITCH) From b9e9fe80522b0b5e08e87f8b93c1bd33514be55e Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 6 Mar 2025 07:41:40 +0530 Subject: [PATCH 02/75] fix: Corrected constellation boilerplate code --- apps/constellation_app/constellation_main.c | 4 ++-- common/cypherock-common | 2 +- common/proto-options/constellation/get_public_key.options | 5 +++++ common/proto-options/constellation/sign_txn.options | 4 ++++ 4 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 common/proto-options/constellation/get_public_key.options create mode 100644 common/proto-options/constellation/sign_txn.options diff --git a/apps/constellation_app/constellation_main.c b/apps/constellation_app/constellation_main.c index 458b7db3c..aa57dc576 100644 --- a/apps/constellation_app/constellation_main.c +++ b/apps/constellation_app/constellation_main.c @@ -125,11 +125,11 @@ void constellation_main(usb_event_t usb_evt, const void *constellation_app_confi switch ((uint8_t)query.which_request) { case CONSTELLATION_QUERY_GET_PUBLIC_KEYS_TAG: case CONSTELLATION_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG: { - constellation_get_pub_keys(&query); + // constellation_get_pub_keys(&query); break; } case CONSTELLATION_QUERY_SIGN_TXN_TAG: { - constellation_sign_transaction(&query); + // constellation_sign_transaction(&query); break; } default: { diff --git a/common/cypherock-common b/common/cypherock-common index 60bf878b5..be16ebadc 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit 60bf878b5863e17c1a8b82a7972a45dd75892a7b +Subproject commit be16ebadc9863206f3bd216d721363f229417eaa diff --git a/common/proto-options/constellation/get_public_key.options b/common/proto-options/constellation/get_public_key.options new file mode 100644 index 000000000..56bb3fdf2 --- /dev/null +++ b/common/proto-options/constellation/get_public_key.options @@ -0,0 +1,5 @@ +# Options for file common/cypherock-common/proto/xrp/get_public_key.proto +xrp.GetPublicKeysDerivationPath.path type:FT_STATIC max_count:5 fixed_length:true +xrp.GetPublicKeysIntiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true +xrp.GetPublicKeysIntiateRequest.derivation_paths type:FT_STATIC max_count:100 fixed_length:true +xrp.GetPublicKeysResultResponse.public_keys type:FT_STATIC max_size:33 max_count:10 fixed_length:true diff --git a/common/proto-options/constellation/sign_txn.options b/common/proto-options/constellation/sign_txn.options new file mode 100644 index 000000000..e83a81089 --- /dev/null +++ b/common/proto-options/constellation/sign_txn.options @@ -0,0 +1,4 @@ +# Options for file common/cypherock-common/proto/xrp/sign_txn.proto +xrp.SignTxnInitiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true +xrp.SignTxnInitiateRequest.derivation_path type:FT_STATIC max_count:5 fixed_length:true +xrp.SignTxnSignatureResponse.signature type:FT_STATIC max_size:72 fixed_length:false From 5b0f6a7746b3acec9912a81719b8c1ba2f65b3d3 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 6 Mar 2025 14:26:40 +0530 Subject: [PATCH 03/75] fix: Constellation proto options --- .../proto-options/constellation/get_public_key.options | 10 +++++----- common/proto-options/constellation/sign_txn.options | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/common/proto-options/constellation/get_public_key.options b/common/proto-options/constellation/get_public_key.options index 56bb3fdf2..e45057963 100644 --- a/common/proto-options/constellation/get_public_key.options +++ b/common/proto-options/constellation/get_public_key.options @@ -1,5 +1,5 @@ -# Options for file common/cypherock-common/proto/xrp/get_public_key.proto -xrp.GetPublicKeysDerivationPath.path type:FT_STATIC max_count:5 fixed_length:true -xrp.GetPublicKeysIntiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true -xrp.GetPublicKeysIntiateRequest.derivation_paths type:FT_STATIC max_count:100 fixed_length:true -xrp.GetPublicKeysResultResponse.public_keys type:FT_STATIC max_size:33 max_count:10 fixed_length:true +# Options for file common/cypherock-common/proto/constellation/get_public_key.proto +constellation.GetPublicKeysDerivationPath.path type:FT_STATIC max_count:5 fixed_length:true +constellation.GetPublicKeysIntiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true +constellation.GetPublicKeysIntiateRequest.derivation_paths type:FT_STATIC max_count:100 fixed_length:true +constellation.GetPublicKeysResultResponse.public_keys type:FT_STATIC max_size:33 max_count:10 fixed_length:true diff --git a/common/proto-options/constellation/sign_txn.options b/common/proto-options/constellation/sign_txn.options index e83a81089..2b221fe2d 100644 --- a/common/proto-options/constellation/sign_txn.options +++ b/common/proto-options/constellation/sign_txn.options @@ -1,4 +1,4 @@ -# Options for file common/cypherock-common/proto/xrp/sign_txn.proto -xrp.SignTxnInitiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true -xrp.SignTxnInitiateRequest.derivation_path type:FT_STATIC max_count:5 fixed_length:true -xrp.SignTxnSignatureResponse.signature type:FT_STATIC max_size:72 fixed_length:false +# Options for file common/cypherock-common/proto/constellation/sign_txn.proto +constellation.SignTxnInitiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true +constellation.SignTxnInitiateRequest.derivation_path type:FT_STATIC max_count:5 fixed_length:true +constellation.SignTxnSignatureResponse.signature type:FT_STATIC max_size:72 fixed_length:false From 3e36ebc195e3d3ba248d48bb64cbf79bd29dd46b Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 6 Mar 2025 16:05:03 +0530 Subject: [PATCH 04/75] fix: Code formatting --- apps/constellation_app/constellation_api.c | 28 +++++++------ apps/constellation_app/constellation_api.h | 30 ++++++++------ .../constellation_app/constellation_context.h | 9 ++-- .../constellation_app/constellation_helpers.c | 10 +++-- apps/constellation_app/constellation_main.c | 41 +++++++++++-------- apps/constellation_app/constellation_priv.h | 13 +++--- 6 files changed, 74 insertions(+), 57 deletions(-) diff --git a/apps/constellation_app/constellation_api.c b/apps/constellation_app/constellation_api.c index 0204f6d79..d11cd0099 100644 --- a/apps/constellation_app/constellation_api.c +++ b/apps/constellation_app/constellation_api.c @@ -101,11 +101,11 @@ * GLOBAL FUNCTIONS *****************************************************************************/ bool decode_constellation_query(const uint8_t *data, - uint16_t data_size, - constellation_query_t *query_out) { + uint16_t data_size, + constellation_query_t *query_out) { if (NULL == data || NULL == query_out || 0 == data_size) { constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_DECODING_FAILED); + ERROR_DATA_FLOW_DECODING_FAILED); return false; } @@ -121,16 +121,16 @@ bool decode_constellation_query(const uint8_t *data, /* Send error to host if status is false*/ if (false == status) { constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_DECODING_FAILED); + ERROR_DATA_FLOW_DECODING_FAILED); } return status; } bool encode_constellation_result(const constellation_result_t *result, - uint8_t *buffer, - uint16_t max_buffer_len, - size_t *bytes_written_out) { + uint8_t *buffer, + uint16_t max_buffer_len, + size_t *bytes_written_out) { if (NULL == result || NULL == buffer || NULL == bytes_written_out) return false; @@ -147,10 +147,11 @@ bool encode_constellation_result(const constellation_result_t *result, return status; } -bool check_constellation_query(const constellation_query_t *query, pb_size_t exp_query_tag) { +bool check_constellation_query(const constellation_query_t *query, + pb_size_t exp_query_tag) { if ((NULL == query) || (exp_query_tag != query->which_request)) { constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_QUERY); + ERROR_DATA_FLOW_INVALID_QUERY); return false; } return true; @@ -163,7 +164,8 @@ constellation_result_t init_constellation_result(pb_size_t result_tag) { } void constellation_send_error(pb_size_t which_error, uint32_t error_code) { - constellation_result_t result = init_constellation_result(CONSTELLATION_RESULT_COMMON_ERROR_TAG); + constellation_result_t result = + init_constellation_result(CONSTELLATION_RESULT_COMMON_ERROR_TAG); result.common_error = init_common_error(which_error, error_code); constellation_send_result(&result); } @@ -172,11 +174,13 @@ void constellation_send_result(const constellation_result_t *result) { // TODO: Set all option files uint8_t buffer[1700] = {0}; size_t bytes_encoded = 0; - ASSERT(encode_constellation_result(result, buffer, sizeof(buffer), &bytes_encoded)); + ASSERT(encode_constellation_result( + result, buffer, sizeof(buffer), &bytes_encoded)); send_response_to_host(&buffer[0], bytes_encoded); } -bool constellation_get_query(constellation_query_t *query, pb_size_t exp_query_tag) { +bool constellation_get_query(constellation_query_t *query, + pb_size_t exp_query_tag) { evt_status_t event = get_events(EVENT_CONFIG_USB, MAX_INACTIVITY_TIMEOUT); if (true == event.p0_event.flag) { diff --git a/apps/constellation_app/constellation_api.h b/apps/constellation_app/constellation_api.h index 7e6fb467c..57565db62 100644 --- a/apps/constellation_app/constellation_api.h +++ b/apps/constellation_app/constellation_api.h @@ -1,7 +1,8 @@ /** * @file constellation_api.h * @author Cypherock X1 Team - * @brief Header file to export some helper functions for the CONSTELLATION app + * @brief Header file to export some helper functions for the CONSTELLATION + * app * @copyright Copyright (c) 2025 HODL TECH PTE LTD *
You may obtain a copy of license at https://mitcc.org/ @@ -13,8 +14,8 @@ * INCLUDES *****************************************************************************/ -#include #include +#include /***************************************************************************** * MACROS AND DEFINES @@ -37,17 +38,20 @@ * * @param[in] data: PB encoded bytestream received from host * @param[in] data_size: size of pb encoded bytestream - * @param[out] query_out: @ref constellation_query_t obj to copy the decoded result to + * @param[out] query_out: @ref constellation_query_t obj to copy the decoded + * result to * @return bool True if decoding was successful, else false */ bool decode_constellation_query(const uint8_t *data, - uint16_t data_size, - constellation_query_t *query_out); + uint16_t data_size, + constellation_query_t *query_out); /** - * @brief Encodes the CONSTELLATION result with `CONSTELLATION_RESULT_FIELDS` to byte-stream + * @brief Encodes the CONSTELLATION result with `CONSTELLATION_RESULT_FIELDS` to + * byte-stream * - * @param[in] result: object of populated @ref constellation_result_t to be encoded + * @param[in] result: object of populated @ref constellation_result_t to be + * encoded * @param[out] buffer: buffer to fill byte-stream into * @param[in] max_buffer_len: Max length allowed for writing bytestream to * buffer @@ -55,9 +59,9 @@ bool decode_constellation_query(const uint8_t *data, * @return bool True if decoding was successful, else false */ bool encode_constellation_result(const constellation_result_t *result, - uint8_t *buffer, - uint16_t max_buffer_len, - size_t *bytes_written_out); + uint8_t *buffer, + uint16_t max_buffer_len, + size_t *bytes_written_out); /** * @brief This API checks if the `which_request` field of the query of type @@ -68,7 +72,8 @@ bool encode_constellation_result(const constellation_result_t *result, * @return true If the query tag matches the expected tag * @return false If the query tag does not match the expected tag */ -bool check_constellation_query(const constellation_query_t *query, pb_size_t exp_query_tag); +bool check_constellation_query(const constellation_query_t *query, + pb_size_t exp_query_tag); /** * @brief Returns zero initialized object of type @@ -108,6 +113,7 @@ void constellation_send_result(const constellation_result_t *result); * @return false If the request timed out or the recieved request did not match * the tag */ -bool constellation_get_query(constellation_query_t *query, pb_size_t exp_query_tag); +bool constellation_get_query(constellation_query_t *query, + pb_size_t exp_query_tag); #endif diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h index b21e5afeb..08ab574dd 100644 --- a/apps/constellation_app/constellation_context.h +++ b/apps/constellation_app/constellation_context.h @@ -23,11 +23,10 @@ #define CONSTELLATION_IMPLICIT_ACCOUNT_DEPTH 5 -#define CONSTELLATION_PURPOSE_INDEX 0x8000002C // 44' -#define CONSTELLATION_COIN_INDEX 0x80000000 + 1137 // 1137' -#define CONSTELLATION_ACCOUNT_INDEX 0x80000000 // 0' -#define CONSTELLATION_CHANGE_INDEX 0x00000000 // 0 - +#define CONSTELLATION_PURPOSE_INDEX 0x8000002C // 44' +#define CONSTELLATION_COIN_INDEX 0x80000000 + 1137 // 1137' +#define CONSTELLATION_ACCOUNT_INDEX 0x80000000 // 0' +#define CONSTELLATION_CHANGE_INDEX 0x00000000 // 0 #define CONSTELLATION_PUB_KEY_SIZE 33 #define CONSTELLATION_UNCOMPRESSED_PUB_KEY_SIZE 65 diff --git a/apps/constellation_app/constellation_helpers.c b/apps/constellation_app/constellation_helpers.c index 85a4efc3a..1eb8bc731 100644 --- a/apps/constellation_app/constellation_helpers.c +++ b/apps/constellation_app/constellation_helpers.c @@ -61,8 +61,9 @@ *****************************************************************************/ #include "constellation_helpers.h" -#include "constellation_context.h" + #include "coin_utils.h" +#include "constellation_context.h" /***************************************************************************** * EXTERN VARIABLES @@ -106,9 +107,10 @@ bool constellation_derivation_path_guard(const uint32_t *path, uint8_t levels) { change = path[3], address = path[4]; // m/44'/144'/0'/0/i - status = (CONSTELLATION_PURPOSE_INDEX == purpose && CONSTELLATION_COIN_INDEX == coin && - CONSTELLATION_ACCOUNT_INDEX == account && CONSTELLATION_CHANGE_INDEX == change && - is_non_hardened(address)); + status = (CONSTELLATION_PURPOSE_INDEX == purpose && + CONSTELLATION_COIN_INDEX == coin && + CONSTELLATION_ACCOUNT_INDEX == account && + CONSTELLATION_CHANGE_INDEX == change && is_non_hardened(address)); return status; } diff --git a/apps/constellation_app/constellation_main.c b/apps/constellation_app/constellation_main.c index aa57dc576..4c5a331ae 100644 --- a/apps/constellation_app/constellation_main.c +++ b/apps/constellation_app/constellation_main.c @@ -1,7 +1,8 @@ /** * @file constellation_main.c * @author Cypherock X1 Team - * @brief A common entry point to various CONSTELLATION coin actions supported. + * @brief A common entry point to various CONSTELLATION coin actions + *supported. * @copyright Copyright (c) 2025 HODL TECH PTE LTD *
You may obtain a copy of license at https://mitcc.org/ @@ -62,9 +63,9 @@ #include "constellation_main.h" -#include "status_api.h" #include "constellation_api.h" #include "constellation_priv.h" +#include "status_api.h" /***************************************************************************** * EXTERN VARIABLES @@ -86,35 +87,39 @@ * STATIC FUNCTION PROTOTYPES *****************************************************************************/ /** - * @brief Entry point for the CONSTELLATION application of the X1 vault. It is invoked - * by the X1 vault firmware, as soon as there is a USB request raised for the - * Constellation app. + * @brief Entry point for the CONSTELLATION application of the X1 vault. It is + * invoked by the X1 vault firmware, as soon as there is a USB request raised + * for the Constellation app. * - * @param usb_evt The USB event which triggered invocation of the constellation app + * @param usb_evt The USB event which triggered invocation of the constellation + * app */ -void constellation_main(usb_event_t usb_evt, const void *constellation_app_config); +void constellation_main(usb_event_t usb_evt, + const void *constellation_app_config); /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ static const cy_app_desc_t constellation_app_desc = {.id = 23, - .version = - { - .major = 1, - .minor = 0, - .patch = 0, - }, - .app = constellation_main, - .app_config = NULL}; + .version = + { + .major = 1, + .minor = 0, + .patch = 0, + }, + .app = constellation_main, + .app_config = NULL}; /***************************************************************************** * STATIC FUNCTIONS *****************************************************************************/ -void constellation_main(usb_event_t usb_evt, const void *constellation_app_config) { +void constellation_main(usb_event_t usb_evt, + const void *constellation_app_config) { constellation_query_t query = CONSTELLATION_QUERY_INIT_DEFAULT; - if (false == decode_constellation_query(usb_evt.p_msg, usb_evt.msg_size, &query)) { + if (false == + decode_constellation_query(usb_evt.p_msg, usb_evt.msg_size, &query)) { return; } @@ -135,7 +140,7 @@ void constellation_main(usb_event_t usb_evt, const void *constellation_app_confi default: { /* In case we ever encounter invalid query, convey to the host app */ constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_QUERY); + ERROR_DATA_FLOW_INVALID_QUERY); break; } } diff --git a/apps/constellation_app/constellation_priv.h b/apps/constellation_app/constellation_priv.h index 676305a27..f7eb7d35c 100644 --- a/apps/constellation_app/constellation_priv.h +++ b/apps/constellation_app/constellation_priv.h @@ -13,8 +13,8 @@ /***************************************************************************** * INCLUDES *****************************************************************************/ -#include #include +#include #include "constellation_context.h" @@ -32,8 +32,8 @@ /** * @brief Handler for CONSTELLATION public key derivation. - * @details This flow expects CONSTELLATION_GET_PUBLIC_KEY_REQUEST_INITIATE_TAG as initial - * query, otherwise the flow is aborted + * @details This flow expects CONSTELLATION_GET_PUBLIC_KEY_REQUEST_INITIATE_TAG + * as initial query, otherwise the flow is aborted * * @param query object for address public key query */ @@ -41,9 +41,10 @@ void constellation_get_pub_keys(constellation_query_t *query); /** * @brief Handler for signing a transaction on constellation. - * @details The expected request type is CONSTELLATION_SIGN_TXN_REQUEST_INITIATE_TAG. The - * function controls the complete data exchange with host, user prompts and - * confirmations for signing an CONSTELLATION based transaction. + * @details The expected request type is + * CONSTELLATION_SIGN_TXN_REQUEST_INITIATE_TAG. The function controls the + * complete data exchange with host, user prompts and confirmations for signing + * an CONSTELLATION based transaction. * * @param query Reference to the decoded query struct from the host app */ From 642d2738cd811b49f598a105682f94cea2cbea7f Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 6 Mar 2025 15:40:03 +0530 Subject: [PATCH 05/75] feat: Constellation generate pubkey and address --- .../constellation_app/constellation_context.h | 9 +- apps/constellation_app/constellation_main.c | 2 +- .../constellation_app/constellation_pub_key.c | 520 ++++++++++++++++++ 3 files changed, 528 insertions(+), 3 deletions(-) create mode 100644 apps/constellation_app/constellation_pub_key.c diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h index 08ab574dd..c61252ef9 100644 --- a/apps/constellation_app/constellation_context.h +++ b/apps/constellation_app/constellation_context.h @@ -29,8 +29,13 @@ #define CONSTELLATION_CHANGE_INDEX 0x00000000 // 0 #define CONSTELLATION_PUB_KEY_SIZE 33 -#define CONSTELLATION_UNCOMPRESSED_PUB_KEY_SIZE 65 -#define CONSTELLATION_ACCOUNT_ADDRESS_LENGTH 40 +#define CONSTELLATION_UNCOMPRESSED_PUBKEY_SIZE 65 +#define CONSTELLATION_ACCOUNT_ADDRESS_SIZE 40 +#define PKCS_PREFIX_SIZE 23 +#define PKCS_PREFIXED_PUBKEY_SIZE \ + PKCS_PREFIX_SIZE + CONSTELLATION_UNCOMPRESSED_PUBKEY_SIZE +#define SHA256_DIGEST_SIZE 32 +#define BS58_ENCODED_SIZE 45 /***************************************************************************** * TYPEDEFS diff --git a/apps/constellation_app/constellation_main.c b/apps/constellation_app/constellation_main.c index 4c5a331ae..bec5ce24e 100644 --- a/apps/constellation_app/constellation_main.c +++ b/apps/constellation_app/constellation_main.c @@ -130,7 +130,7 @@ void constellation_main(usb_event_t usb_evt, switch ((uint8_t)query.which_request) { case CONSTELLATION_QUERY_GET_PUBLIC_KEYS_TAG: case CONSTELLATION_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG: { - // constellation_get_pub_keys(&query); + constellation_get_pub_keys(&query); break; } case CONSTELLATION_QUERY_SIGN_TXN_TAG: { diff --git a/apps/constellation_app/constellation_pub_key.c b/apps/constellation_app/constellation_pub_key.c new file mode 100644 index 000000000..786291dcb --- /dev/null +++ b/apps/constellation_app/constellation_pub_key.c @@ -0,0 +1,520 @@ +/** + * @file constellation_pub_key.c + * @author Cypherock X1 Team + * @brief Generates public key for CONSTELLATION derivations. + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2024 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include + +#include "base58.h" +#include "bip32.h" +#include "coin_utils.h" +#include "constellation_api.h" +#include "constellation_context.h" +#include "constellation_helpers.h" +#include "constellation_priv.h" +#include "curves.h" +#include "ecdsa.h" +#include "hasher.h" +#include "reconstruct_wallet_flow.h" +#include "secp256k1.h" +#include "sha2.h" +#include "status_api.h" +#include "ui_core_confirm.h" +#include "ui_screens.h" +#include "wallet_list.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Checks if the provided query contains expected request. + * @details The function performs the check on the request type and if the check + * fails, then it will send an error to the host bitcoin app and return false. + * + * @param query Reference to an instance of constellation_query_t containing + * query received from host app + * @param which_request The expected request type enum + * + * @return bool Indicating if the check succeeded or failed + * @retval true If the query contains the expected request + * @retval false If the query does not contain the expected request + */ +static bool check_which_request(const constellation_query_t *query, + pb_size_t which_request); + +/** + * @brief Validates the derivation paths received in the request from host + * @details The function validates each path index in the request. If any + * invalid index is detected, the function will send an error to the host and + * return false. + * + * @param req Reference to an instance of + * constellation_get_public_keys_intiate_request_t + * @param which_request The type of request received from the host. + * @return bool Indicating if the verification passed or failed + * @retval true If the derivation path entries are valid + * @retval false If any of the derivation path entries are invalid + */ +static bool validate_request( + const constellation_get_public_keys_intiate_request_t *req, + const pb_size_t which_request); + +/** + * @brief Fills the list of public keys corresponding to the provided list of + * derivation paths in the buffer + * @details The function expects the size of list for derivation paths and + * location for storing derived public keys to be a match with provided count. + * + * @param path Reference to the list of + * constellation_get_public_keys_derivation_path_t + * @param seed Reference to a const array containing the seed + * @param public_key Reference to the location to store all the public keys to + * be derived + * @param count Number of derivation paths in the list and consequently, + * sufficient space in memory for storing derived public keys. + * + * @retval true If all the requested public keys were derived successfully + * @retval false If there is any issue occurred during the key derivation + */ +static bool fill_public_keys( + const constellation_get_public_keys_derivation_path_t *path, + const uint8_t *seed, + uint8_t public_key_list[][CONSTELLATION_PUB_KEY_SIZE], + pb_size_t count); + +/** + * @brief The function sends public keys for the requested batch + * @details The function determines the batch size from the static struct + * member declaration of nanopb options. The function batches the result based + * on the definition and sends the result. The function expects that the entire + * list of public keys requested is already derived and provided to this + * function as pubkey_list. The function will return false if either the query + * was wrong or a P0 event is occurred. In case of wrong query, the function + * also sends an error to the host app. + * + * @param query Reference to an instance of constellation_query_t + * @param pubkey_list Reference to list of derived public key to be sent to the + * host + * @param count Number of public keys entries in the list of public keys + * @param which_request The type of request to be expected from the host + * @param which_response The type of response to be sent to the host + * + * @return bool Indicating if the public keys was exported completely to the + * host + * @retval true If all the requested public keys were exported to the host app + * @retval false If the export was interrupted by a P0 event or an invalid query + * was received from the host app. + */ +static bool send_public_keys( + constellation_query_t *query, + const uint8_t pubkey_list[][CONSTELLATION_PUB_KEY_SIZE], + const pb_size_t count, + const pb_size_t which_request, + const pb_size_t which_response); + +/** + * @details The function provides an ED25519 public key for CONSTELLATION. It + * accepts NULL for output parameter and handles accordingly. The function also + * manages all the terminal errors during derivation/encoding, in which case it + * will return false and send a relevant error to the host closing the + * request-response pair All the errors/invalid cases are conveyed to the host + * as unknown_error = 1 because we expect the data validation was success. + * TODO: Make this a common utility function + * + * @param seed Reference to the wallet seed generated + * @param path Derivation path of the node to be derived + * @param path_length Expected length of the provided derivation path + * @param public_key Storage location for raw uncompressed public key + * + * @retval false If derivation failed + */ +static bool get_public_key(const uint8_t *seed, + const uint32_t *path, + uint32_t path_length, + uint8_t *public_key); + +/** + * @brief Helper function to take user consent before exporting public keys to + * the host. Uses an appropriate message template based on the query request + * received from the host. + * + * @param which_request The type of request received from host + * @param wallet_name The name of the wallet on which the request needs to be + * performed + * @return true If the user accepted the request + * @return false If the user rejected or any P0 event occurred during the + * confirmation. + */ +static bool get_user_consent(const pb_size_t which_request, + const char *wallet_name); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/// Ref: +/// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/key-store.ts#L39 +static const uint8_t PKCS_PREFIX[PKCS_PREFIX_SIZE] = { + 0x30, 0x56, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, 0x03, 0x42, 0x00}; + +static bool check_which_request(const constellation_query_t *query, + pb_size_t which_request) { + if (which_request != query->get_public_keys.which_request) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + return true; +} + +static bool validate_request( + const constellation_get_public_keys_intiate_request_t *req, + const pb_size_t which_request) { + bool status = true; + const pb_size_t count = req->derivation_paths_count; + + if (0 == count) { + // request does not have any derivation paths, invalid request + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + status = false; + } + + if (CONSTELLATION_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG == which_request && + 1 < count) { + // `CONSTELLATION_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG` request contains + // more than one derivation path which is not expected + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + status = false; + } + + const constellation_get_public_keys_derivation_path_t *path = NULL; + + for (pb_size_t index = 0; index < count; index++) { + path = &req->derivation_paths[index]; + if (!constellation_derivation_path_guard(path->path, path->path_count)) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + status = false; + break; + } + } + + return status; +} + +static bool get_public_key(const uint8_t *seed, + const uint32_t *path, + uint32_t path_length, + uint8_t *public_key) { + HDNode node = {0}; + + if (!derive_hdnode_from_path( + path, path_length, SECP256K1_NAME, seed, &node)) { + // send unknown error; unknown failure reason + constellation_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 1); + memzero(&node, sizeof(HDNode)); + return false; + } + + if (NULL != public_key) { + memcpy(public_key, node.public_key, CONSTELLATION_PUB_KEY_SIZE); + } + + memzero(&node, sizeof(HDNode)); + return true; +} + +static bool fill_public_keys( + const constellation_get_public_keys_derivation_path_t *path, + const uint8_t *seed, + uint8_t public_key_list[][CONSTELLATION_PUB_KEY_SIZE], + pb_size_t count) { + for (pb_size_t index = 0; index < count; index++) { + const constellation_get_public_keys_derivation_path_t *current = + &path[index]; + if (!get_public_key( + seed, current->path, current->path_count, public_key_list[index])) { + return false; + } + } + + return true; +} + +static bool send_public_keys( + constellation_query_t *query, + const uint8_t pubkey_list[][CONSTELLATION_PUB_KEY_SIZE], + const pb_size_t count, + const pb_size_t which_request, + const pb_size_t which_response) { + constellation_result_t response = init_constellation_result(which_response); + constellation_get_public_keys_result_response_t *result = + &response.get_public_keys.result; + size_t batch_limit = sizeof(response.get_public_keys.result.public_keys) / + CONSTELLATION_PUB_KEY_SIZE; + size_t remaining = count; + + response.get_public_keys.which_response = + CONSTELLATION_GET_PUBLIC_KEYS_RESPONSE_RESULT_TAG; + while (true) { + // send response as batched list of public keys + size_t batch_size = CY_MIN(batch_limit, remaining); + result->public_keys_count = batch_size; + + memcpy(result->public_keys, + &pubkey_list[count - remaining], + batch_size * CONSTELLATION_PUB_KEY_SIZE); + + constellation_send_result(&response); + remaining -= batch_size; + if (0 == remaining) { + break; + } + + if (!constellation_get_query(query, which_request) || + !check_which_request( + query, CONSTELLATION_GET_PUBLIC_KEYS_REQUEST_FETCH_NEXT_TAG)) { + return false; + } + } + return true; +} + +static bool get_user_consent(const pb_size_t which_request, + const char *wallet_name) { + char msg[100] = ""; + + if (CONSTELLATION_QUERY_GET_PUBLIC_KEYS_TAG == which_request) { + snprintf(msg, + sizeof(msg), + UI_TEXT_ADD_ACCOUNT_PROMPT, + CONSTELLATION_NAME, + wallet_name); + } else { + snprintf(msg, + sizeof(msg), + UI_TEXT_RECEIVE_PROMPT, + CONSTELLATION_NAME, + wallet_name); + } + + return core_scroll_page(NULL, msg, constellation_send_error); +} + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ +bool generate_dag_address(char *address, const uint8_t *pubkey) { + // address = 'DAG' + par + bs58_last36 + // bs58_last36 = last 36 chars of bs58enc(prefixed_uncompressed_pubkey) + // par = sum(numeric chars in bs58_last36) % 9 + // prefixed_uncompressed_pubkey = pkcs_prefix + uncompressed_pubkey + // see + // https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/key-store.ts#L230 + + uint8_t uncompressed_pubkey[CONSTELLATION_UNCOMPRESSED_PUBKEY_SIZE] = {0}; + uint8_t pkcs_prefixed_pubkey[PKCS_PREFIXED_PUBKEY_SIZE] = {0}; + uint8_t key_digest[SHA256_DIGEST_SIZE] = {0}; + char bs58_encoded_key[BS58_ENCODED_SIZE] = "\0"; + size_t res_size = BS58_ENCODED_SIZE; + + ecdsa_uncompress_pubkey(&secp256k1, pubkey, uncompressed_pubkey); + + memcpy(pkcs_prefixed_pubkey, PKCS_PREFIX, PKCS_PREFIX_SIZE); + memcpy(pkcs_prefixed_pubkey + PKCS_PREFIX_SIZE, + uncompressed_pubkey, + CONSTELLATION_UNCOMPRESSED_PUBKEY_SIZE); + + sha256_Raw(pkcs_prefixed_pubkey, sizeof(pkcs_prefixed_pubkey), key_digest); + + if (!b58enc(bs58_encoded_key, &res_size, key_digest, SHA256_DIGEST_SIZE) || + res_size < 36) { + constellation_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 2); + return false; + } + + const char *bs58_last36 = bs58_encoded_key + res_size - 36 - 1; + + uint64_t sum = 0; + for (size_t i = 0; i < 36; i++) { + if (bs58_last36[i] >= '0' && bs58_last36[i] <= '9') { + sum += bs58_last36[i] - '0'; + } + } + char parity = (sum % 9) + '0'; + + snprintf(address, + CONSTELLATION_ACCOUNT_ADDRESS_SIZE + 1, + "DAG%c%.*s", + parity, + 36, + bs58_last36); + + return true; +} + +void constellation_get_pub_keys(constellation_query_t *query) { + char wallet_name[NAME_SIZE] = ""; + uint8_t seed[64] = {0}; + + const pb_size_t which_request = query->which_request; + const constellation_get_public_keys_intiate_request_t *init_req = NULL; + pb_size_t which_response; + + if (CONSTELLATION_QUERY_GET_PUBLIC_KEYS_TAG == which_request) { + which_response = CONSTELLATION_RESULT_GET_PUBLIC_KEYS_TAG; + init_req = &query->get_public_keys.initiate; + } else { + which_response = CONSTELLATION_RESULT_GET_USER_VERIFIED_PUBLIC_KEY_TAG; + init_req = &query->get_user_verified_public_key.initiate; + } + + const pb_size_t count = init_req->derivation_paths_count; + + uint8_t pubkey_list[sizeof(init_req->derivation_paths) / + sizeof(constellation_get_public_keys_derivation_path_t)] + [CONSTELLATION_PUB_KEY_SIZE] = {0}; + + if (!check_which_request( + query, CONSTELLATION_GET_PUBLIC_KEYS_REQUEST_INITIATE_TAG) || + !validate_request(init_req, which_request) || + !get_wallet_name_by_id(init_req->wallet_id, + (uint8_t *)wallet_name, + constellation_send_error)) { + return; + } + + // Take user consent to export public key for the wallet + if (!get_user_consent(which_request, wallet_name)) { + return; + } + + set_app_flow_status(CONSTELLATION_GET_PUBLIC_KEYS_STATUS_CONFIRM); + + if (!reconstruct_seed( + init_req->wallet_id, &seed[0], constellation_send_error)) { + memzero(seed, sizeof(seed)); + return; + } + + set_app_flow_status(CONSTELLATION_GET_PUBLIC_KEYS_STATUS_SEED_GENERATED); + delay_scr_init(ui_text_processing, DELAY_SHORT); + + bool result = + fill_public_keys(init_req->derivation_paths, seed, pubkey_list, count); + + // Clear seed as soon as it is not needed + memzero(seed, sizeof(seed)); + + if (!result) { + // send unknown error; do not know failure reason + constellation_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 1); + return; + } + + // In case the request is to `CONSTELLATION_QUERY_GET_PUBLIC_KEY_TAG` type, + // then wait for user verification of the address + if (CONSTELLATION_QUERY_GET_USER_VERIFIED_PUBLIC_KEY_TAG == which_request) { + char address[CONSTELLATION_ACCOUNT_ADDRESS_SIZE + 1] = "\0"; + if (!generate_dag_address(address, pubkey_list[0])) { + return; + } + + if (!core_scroll_page( + ui_text_receive_on, address, constellation_send_error)) { + return; + } + set_app_flow_status(CONSTELLATION_GET_PUBLIC_KEYS_STATUS_VERIFY); + } + + if (!send_public_keys( + query, pubkey_list, count, which_request, which_response)) { + return; + } + + delay_scr_init(ui_text_check_cysync_app, DELAY_TIME); + return; +} From bb1679ea62dcd01b0ef6de5ed61570a0f7e50383 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 6 Mar 2025 20:47:57 +0530 Subject: [PATCH 06/75] fix: Return uncompressed pubkey in constellation app --- apps/constellation_app/constellation_context.h | 6 ++---- apps/constellation_app/constellation_pub_key.c | 10 +++------- .../proto-options/constellation/get_public_key.options | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h index c61252ef9..4efa19302 100644 --- a/apps/constellation_app/constellation_context.h +++ b/apps/constellation_app/constellation_context.h @@ -28,12 +28,10 @@ #define CONSTELLATION_ACCOUNT_INDEX 0x80000000 // 0' #define CONSTELLATION_CHANGE_INDEX 0x00000000 // 0 -#define CONSTELLATION_PUB_KEY_SIZE 33 -#define CONSTELLATION_UNCOMPRESSED_PUBKEY_SIZE 65 +#define CONSTELLATION_PUB_KEY_SIZE 65 #define CONSTELLATION_ACCOUNT_ADDRESS_SIZE 40 #define PKCS_PREFIX_SIZE 23 -#define PKCS_PREFIXED_PUBKEY_SIZE \ - PKCS_PREFIX_SIZE + CONSTELLATION_UNCOMPRESSED_PUBKEY_SIZE +#define PKCS_PREFIXED_PUBKEY_SIZE PKCS_PREFIX_SIZE + CONSTELLATION_PUB_KEY_SIZE #define SHA256_DIGEST_SIZE 32 #define BS58_ENCODED_SIZE 45 diff --git a/apps/constellation_app/constellation_pub_key.c b/apps/constellation_app/constellation_pub_key.c index 786291dcb..675b6ed41 100644 --- a/apps/constellation_app/constellation_pub_key.c +++ b/apps/constellation_app/constellation_pub_key.c @@ -292,7 +292,7 @@ static bool get_public_key(const uint8_t *seed, } if (NULL != public_key) { - memcpy(public_key, node.public_key, CONSTELLATION_PUB_KEY_SIZE); + ecdsa_uncompress_pubkey(&secp256k1, node.public_key, public_key); } memzero(&node, sizeof(HDNode)); @@ -395,18 +395,15 @@ bool generate_dag_address(char *address, const uint8_t *pubkey) { // see // https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/key-store.ts#L230 - uint8_t uncompressed_pubkey[CONSTELLATION_UNCOMPRESSED_PUBKEY_SIZE] = {0}; uint8_t pkcs_prefixed_pubkey[PKCS_PREFIXED_PUBKEY_SIZE] = {0}; uint8_t key_digest[SHA256_DIGEST_SIZE] = {0}; char bs58_encoded_key[BS58_ENCODED_SIZE] = "\0"; size_t res_size = BS58_ENCODED_SIZE; - ecdsa_uncompress_pubkey(&secp256k1, pubkey, uncompressed_pubkey); - memcpy(pkcs_prefixed_pubkey, PKCS_PREFIX, PKCS_PREFIX_SIZE); memcpy(pkcs_prefixed_pubkey + PKCS_PREFIX_SIZE, - uncompressed_pubkey, - CONSTELLATION_UNCOMPRESSED_PUBKEY_SIZE); + pubkey, + CONSTELLATION_PUB_KEY_SIZE); sha256_Raw(pkcs_prefixed_pubkey, sizeof(pkcs_prefixed_pubkey), key_digest); @@ -516,5 +513,4 @@ void constellation_get_pub_keys(constellation_query_t *query) { } delay_scr_init(ui_text_check_cysync_app, DELAY_TIME); - return; } diff --git a/common/proto-options/constellation/get_public_key.options b/common/proto-options/constellation/get_public_key.options index e45057963..579a84b1b 100644 --- a/common/proto-options/constellation/get_public_key.options +++ b/common/proto-options/constellation/get_public_key.options @@ -2,4 +2,4 @@ constellation.GetPublicKeysDerivationPath.path type:FT_STATIC max_count:5 fixed_length:true constellation.GetPublicKeysIntiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true constellation.GetPublicKeysIntiateRequest.derivation_paths type:FT_STATIC max_count:100 fixed_length:true -constellation.GetPublicKeysResultResponse.public_keys type:FT_STATIC max_size:33 max_count:10 fixed_length:true +constellation.GetPublicKeysResultResponse.public_keys type:FT_STATIC max_size:65 max_count:10 fixed_length:true From 1a04b5081816183f0b396aebf785dbfedf7d4338 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 6 Mar 2025 22:57:47 +0530 Subject: [PATCH 07/75] fix: Corrected constellatio generate address pseudo code --- apps/constellation_app/constellation_pub_key.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/constellation_app/constellation_pub_key.c b/apps/constellation_app/constellation_pub_key.c index 675b6ed41..3d745d8bd 100644 --- a/apps/constellation_app/constellation_pub_key.c +++ b/apps/constellation_app/constellation_pub_key.c @@ -388,10 +388,10 @@ static bool get_user_consent(const pb_size_t which_request, * GLOBAL FUNCTIONS *****************************************************************************/ bool generate_dag_address(char *address, const uint8_t *pubkey) { - // address = 'DAG' + par + bs58_last36 - // bs58_last36 = last 36 chars of bs58enc(prefixed_uncompressed_pubkey) - // par = sum(numeric chars in bs58_last36) % 9 - // prefixed_uncompressed_pubkey = pkcs_prefix + uncompressed_pubkey + // address = 'DAG' + parity + bs58_last36 + // bs58_last36 = last 36 chars of bs58enc(sha256(pkcs_prefixed_pubkey)) + // parity = sum(numeric chars in bs58_last36) % 9 + // pkcs_prefixed_pubkey = pkcs_prefix + uncompressed_pubkey // see // https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/key-store.ts#L230 From 32d223fac230efc97af214210dd93a19c18b4bcc Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Sat, 8 Mar 2025 15:34:53 +0530 Subject: [PATCH 08/75] feat: Added sign txn functionality to constellation app --- .../constellation_app/constellation_helpers.c | 123 ++++- .../constellation_app/constellation_helpers.h | 17 + apps/constellation_app/constellation_main.c | 2 +- apps/constellation_app/constellation_priv.h | 10 + apps/constellation_app/constellation_txn.c | 449 ++++++++++++++++++ common/cypherock-common | 2 +- .../constellation/sign_txn.options | 6 + src/constant_texts.h | 1 + 8 files changed, 607 insertions(+), 3 deletions(-) create mode 100644 apps/constellation_app/constellation_txn.c diff --git a/apps/constellation_app/constellation_helpers.c b/apps/constellation_app/constellation_helpers.c index 1eb8bc731..09febbb51 100644 --- a/apps/constellation_app/constellation_helpers.c +++ b/apps/constellation_app/constellation_helpers.c @@ -59,9 +59,12 @@ /***************************************************************************** * INCLUDES *****************************************************************************/ - #include "constellation_helpers.h" +#include +#include +#include + #include "coin_utils.h" #include "constellation_context.h" @@ -114,3 +117,121 @@ bool constellation_derivation_path_guard(const uint32_t *path, uint8_t levels) { return status; } + +/// Ref: +// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/transaction-v2.ts#L113 +void encode_txn(const constellation_transaction_t *txn, char *output) { + char temp[1024] = ""; + char buffer[32] = ""; + + // Parent count (always "2") + strcat(temp, "2"); + + // Source address length and value + snprintf(buffer, sizeof(buffer), "%u", strlen(txn->source)); + strcat(temp, buffer); + strcat(temp, txn->source); + + // Destination address length and value + snprintf(buffer, sizeof(buffer), "%u", strlen(txn->destination)); + strcat(temp, buffer); + strcat(temp, txn->destination); + + // Amount length and value (hex string) + char hex_str_amount[16] = ""; + snprintf(hex_str_amount, sizeof(hex_str_amount), "%llx", txn->amount); + snprintf(buffer, sizeof(buffer), "%u", strlen(hex_str_amount)); + strcat(temp, buffer); + strcat(temp, hex_str_amount); + + // Parent hash length and value + snprintf(buffer, sizeof(buffer), "%u", strlen(txn->parent.hash)); + strcat(temp, buffer); + strcat(temp, txn->parent.hash); + + // Ordinal length and value + char str_ordinal[32] = ""; + snprintf(str_ordinal, sizeof(str_ordinal), "%lu", txn->parent.ordinal); + snprintf(buffer, sizeof(buffer), "%u", strlen(str_ordinal)); + strcat(temp, buffer); + strcat(temp, str_ordinal); + + // Fee length and value + char str_fee[32] = ""; + snprintf(str_fee, sizeof(str_fee), "%lu", txn->fee); + snprintf(buffer, sizeof(buffer), "%u", strlen(str_fee)); + strcat(temp, buffer); + strcat(temp, str_fee); + + // Salt length and value + snprintf(buffer, sizeof(buffer), "%u", strlen(txn->salt)); + strcat(temp, buffer); + strcat(temp, txn->salt); + + strcpy(output, temp); +} + +// Encode a variable-length integer (similar to utf8Length in JS) +/// Ref: +// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/tx-encode.ts#L81 +void encode_var_length(uint32_t value, uint8_t *output, size_t *out_len) { + size_t position = 0; + + if (value < (1 << 6)) { + output[position++] = (value | 0x80); + } else if (value < (1 << 13)) { + output[position++] = ((value & 0x3F) | 0xC0); + output[position++] = (value >> 6); + } else if (value < (1 << 20)) { + output[position++] = ((value & 0x3F) | 0xC0); + output[position++] = ((value >> 6) | 0x80); + output[position++] = (value >> 13); + } else if (value < (1 << 27)) { + output[position++] = ((value & 0x3F) | 0xC0); + output[position++] = ((value >> 6) | 0x80); + output[position++] = ((value >> 13) | 0x80); + output[position++] = (value >> 20); + } else { + output[position++] = ((value & 0x3F) | 0xC0); + output[position++] = ((value >> 6) | 0x80); + output[position++] = ((value >> 13) | 0x80); + output[position++] = ((value >> 20) | 0x80); + output[position++] = (value >> 27); + } + *out_len = position; +} + +/// Ref: +// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/tx-encode.ts#L71 +void kryo_serialize(const char *msg, uint8_t *output, size_t *out_len) { + uint8_t length_encoded[5] = {0}; + size_t len = 0; + + // Prefix is "03" + utf8Length(msg length + 1) + encode_var_length(strlen(msg) + 1, length_encoded, &len); + + size_t index = 0; + output[index++] = 0x03; // Prefix "03" + + // Append length encoding + memcpy(&output[index], length_encoded, len); + index += len; + + // Append msg as raw bytes + size_t msg_len = strlen(msg); + memcpy(&output[index], msg, msg_len); + index += msg_len; + + *out_len = index; +} + +/// Ref: +// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/key-store.ts#L337 +void serialize_txn(const constellation_transaction_t *txn, + uint8_t *output, + size_t *output_len) { + char encoded_txn[1024] = ""; + encode_txn(txn, encoded_txn); + + kryo_serialize(encoded_txn, output, output_len); +} \ No newline at end of file diff --git a/apps/constellation_app/constellation_helpers.h b/apps/constellation_app/constellation_helpers.h index ef9ff911f..35ed11faa 100644 --- a/apps/constellation_app/constellation_helpers.h +++ b/apps/constellation_app/constellation_helpers.h @@ -17,6 +17,8 @@ #include #include +#include "constellation/sign_txn.pb.h" + /***************************************************************************** * MACROS AND DEFINES *****************************************************************************/ @@ -49,4 +51,19 @@ */ bool constellation_derivation_path_guard(const uint32_t *path, uint8_t levels); +/** + * @brief Serializes a constellation_transaction_t. + * @details Encodes the transaction as per dag4.js library and + * serializes the encoded txn with kryo_serialize + * + * @param[in] txn The constellation_transaction_t to serialize + * @param[out] output The buffer to hold the serialized txn + * @param[out] output_len The length of the output serialized txn + * + * @return None + */ +void serialize_txn(const constellation_transaction_t *txn, + uint8_t *output, + size_t *output_len); + #endif // CONSTELLATION_HELPERS_H \ No newline at end of file diff --git a/apps/constellation_app/constellation_main.c b/apps/constellation_app/constellation_main.c index bec5ce24e..07ac3c27f 100644 --- a/apps/constellation_app/constellation_main.c +++ b/apps/constellation_app/constellation_main.c @@ -134,7 +134,7 @@ void constellation_main(usb_event_t usb_evt, break; } case CONSTELLATION_QUERY_SIGN_TXN_TAG: { - // constellation_sign_transaction(&query); + constellation_sign_transaction(&query); break; } default: { diff --git a/apps/constellation_app/constellation_priv.h b/apps/constellation_app/constellation_priv.h index f7eb7d35c..8bc10482a 100644 --- a/apps/constellation_app/constellation_priv.h +++ b/apps/constellation_app/constellation_priv.h @@ -21,6 +21,16 @@ /***************************************************************************** * TYPEDEFS *****************************************************************************/ +typedef struct { + /** + * The structure holds the wallet information of the transaction. + * @note Populated by constellation_handle_initiate_query() + */ + constellation_sign_txn_initiate_request_t init_info; + + const constellation_transaction_t *dag_txn; + +} constellation_txn_context_t; /***************************************************************************** * EXPORTED VARIABLES diff --git a/apps/constellation_app/constellation_txn.c b/apps/constellation_app/constellation_txn.c new file mode 100644 index 000000000..7e9ecd1ad --- /dev/null +++ b/apps/constellation_app/constellation_txn.c @@ -0,0 +1,449 @@ +/** + * @file constellation_txn.c + * @author Cypherock X1 Team + * @brief Source file to handle transaction signing logic for CONSTELLATION + *protocol + * + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2024 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include + +#include "coin_utils.h" +#include "constellation/core.pb.h" +#include "constellation/sign_txn.pb.h" +#include "constellation_api.h" +#include "constellation_context.h" +#include "constellation_helpers.h" +#include "constellation_priv.h" +#include "reconstruct_wallet_flow.h" +#include "status_api.h" +#include "ui_core_confirm.h" +#include "ui_screens.h" +#include "utils.h" +#include "wallet_list.h" +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ +typedef constellation_sign_txn_signature_response_signature_t der_sig_t; + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Checks if the provided query contains expected request. + * @details The function performs the check on the request type and if the check + * fails, then it will send an error to the host bitcoin app and return false. + * + * @param query Reference to an instance of constellation_query_t containing + * query received from host app + * @param which_request The expected request type enum + * + * @return bool Indicating if the check succeeded or failed + * @retval true If the query contains the expected request + * @retval false If the query does not contain the expected request + */ +static bool check_which_request(const constellation_query_t *query, + pb_size_t which_request); + +/** + * @brief The function prepares and sends empty responses + * + * @param which_response Constant value for the response type to be sent + */ +static void send_response(const pb_size_t which_response); + +/** + * @brief Validates the derivation path received in the request from host + * @details The function validates the provided account derivation path in the + * request. If invalid path is detected, the function will send an error to the + * host and return false. + * + * @param request Reference to an instance of constellation_sign_txn_request_t + * @return bool Indicating if the verification passed or failed + * @retval true If all the derivation path entries are valid + * @retval false If any of the derivation path entries are invalid + */ +static bool validate_request_data( + const constellation_sign_txn_request_t *request); + +/** + * @brief Takes already received and decoded query for the user confirmation. + * @details The function will verify if the query contains the + * CONSTELLATION_SIGN_TXN_REQUEST_INITIATE_TAG type of request. Additionally, + * the wallet-id is validated for sanity and the derivation path for the account + * is also validated. After the validations, user is prompted about the action + * for confirmation. The function returns true indicating all the validation and + * user confirmation was a success. The function also duplicates the data from + * query into the constellation_txn_context for further processing. + * + * @param query Constant reference to the decoded query received from the host + * + * @return bool Indicating if the function actions succeeded or failed + * @retval true If all the validation and user confirmation was positive + * @retval false If any of the validation or user confirmation was negative + */ +static bool handle_initiate_query(const constellation_query_t *query); + +/** + * @brief Receives unsigned txn from the host. If reception is successful, it + * also parses the txn to ensure it's validity. + * @note In case of any failure, a corresponding message is conveyed to the host + * + * @param query Reference to buffer of type constellation_query_t + * @return true If the txn is received in the internal buffers and is valid + * @return false If the txn could not be received or it's validation failed + */ +static bool fetch_valid_input(constellation_query_t *query); + +/** + * @brief This function executes user verification flow of the unsigned txn + * received from the host. + * @details The user verification flow is different for different type of action + * types identified from the unsigned txn + * @note This function expected that the unsigned txn is parsed using the helper + * function as only few action types are supported currently. + * + * @return true If the user accepted the transaction display + * @return false If any user rejection occured or P0 event occured + */ +static bool get_user_verification(void); + +/** + * @brief Calculates ED25519 curve based signature over the digest of the user + * verified unsigned txn. + * @details Seed reconstruction takes place within this function + * + * @param signature_buffer Reference to buffer where the signature will be + * populated + * @return true If the signature was computed successfully + * @return false If signature could not be computed - maybe due to some error + * during seed reconstruction phase + */ +static bool sign_txn(der_sig_t *der_signature); + +/** + * @brief Sends signature of the CONSTELLATION unsigned txn to the host + * @details The function waits for the host to send a request of type + * CONSTELLATION_SIGN_TXN_REQUEST_SIGNATURE_TAG and sends the response + * + * @param query Reference to buffer of type constellation_query_t + * @param signature Reference to signature to be sent to the host + * @return true If the signature was sent successfully + * @return false If the signature could not be sent - maybe due to and P0 event + * or invalid request received from the host + */ +static bool send_signature(constellation_query_t *query, + const der_sig_t *der_signature); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ +static constellation_txn_context_t *constellation_txn_context = NULL; + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ +static bool check_which_request(const constellation_query_t *query, + pb_size_t which_request) { + if (which_request != query->sign_txn.which_request) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + return true; +} + +static void send_response(const pb_size_t which_response) { + constellation_result_t result = + init_constellation_result(CONSTELLATION_RESULT_SIGN_TXN_TAG); + result.sign_txn.which_response = which_response; + constellation_send_result(&result); +} + +static bool validate_request_data( + const constellation_sign_txn_request_t *request) { + bool status = true; + + if (!constellation_derivation_path_guard( + request->initiate.derivation_path, + request->initiate.derivation_path_count)) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + status = false; + } + return status; +} + +static bool handle_initiate_query(const constellation_query_t *query) { + char wallet_name[NAME_SIZE] = ""; + char msg[100] = ""; + + // TODO: Handle wallet search failures - eg: Wallet ID not found, Wallet + // ID found but is invalid/locked wallet + if (!check_which_request(query, + CONSTELLATION_SIGN_TXN_REQUEST_INITIATE_TAG) || + !validate_request_data(&query->sign_txn) || + !get_wallet_name_by_id(query->sign_txn.initiate.wallet_id, + (uint8_t *)wallet_name, + constellation_send_error)) { + return false; + } + + snprintf(msg, + sizeof(msg), + UI_TEXT_SIGN_TXN_PROMPT, + CONSTELLATION_NAME, + wallet_name); + // Take user consent to sign transaction for the wallet + if (!core_confirmation(msg, constellation_send_error)) { + return false; + } + + set_app_flow_status(CONSTELLATION_SIGN_TXN_STATUS_CONFIRM); + memcpy(&constellation_txn_context->init_info, + &query->sign_txn.initiate, + sizeof(constellation_sign_txn_initiate_request_t)); + + send_response(CONSTELLATION_SIGN_TXN_RESPONSE_CONFIRMATION_TAG); + // show processing screen for a minimum duration (additional time will add due + // to actual processing) + delay_scr_init(ui_text_processing, DELAY_SHORT); + return true; +} + +static bool fetch_valid_input(constellation_query_t *query) { + if (!constellation_get_query(query, CONSTELLATION_QUERY_SIGN_TXN_TAG) && + !check_which_request(query, + CONSTELLATION_SIGN_TXN_REQUEST_TXN_DATA_TAG)) { + return false; + } + + const constellation_sign_txn_data_t *sign_txn_data = + &query->sign_txn.txn_data; + if (sign_txn_data->has_dag_txn == false) { + return false; + } + + constellation_txn_context->dag_txn = &sign_txn_data->dag_txn; + + send_response(CONSTELLATION_SIGN_TXN_RESPONSE_UNSIGNED_TXN_ACCEPTED_TAG); + + return true; +} + +static bool get_user_verification(void) { + const constellation_transaction_t *dag_txn = + constellation_txn_context->dag_txn; + + // verify recipient address + if (!core_scroll_page(ui_text_verify_address, + dag_txn->destination, + constellation_send_error)) { + return false; + } + + // verify recipient amount + char amount_string[30] = {'\0'}; + double decimal_amount = (double)dag_txn->amount; + decimal_amount *= 1e-8; + snprintf(amount_string, sizeof(amount_string), "%.*g", 8, decimal_amount); + + char display[100] = {'\0'}; + snprintf(display, + sizeof(display), + UI_TEXT_VERIFY_AMOUNT, + amount_string, + CONSTELLATION_LUNIT); + + if (!core_confirmation(display, constellation_send_error)) { + return false; + } + + // verify fee + char fee_string[30] = {'\0'}; + double decimal_fee = (double)dag_txn->fee; + decimal_fee *= 1e-8; + snprintf(fee_string, sizeof(fee_string), "%.*g", 8, decimal_fee); + + char fee_display[100] = {'\0'}; + snprintf(fee_display, + sizeof(fee_display), + UI_TEXT_VERIFY_FEE, + fee_string, + CONSTELLATION_LUNIT); + + if (!core_confirmation(fee_display, constellation_send_error)) { + return false; + } + + set_app_flow_status(CONSTELLATION_SIGN_TXN_STATUS_VERIFY); + + return true; +} + +static bool sign_txn(der_sig_t *der_signature) { + uint8_t seed[64] = {0}; + if (!reconstruct_seed(constellation_txn_context->init_info.wallet_id, + seed, + constellation_send_error)) { + memzero(seed, sizeof(seed)); + // TODO: handle errors of reconstruction flow + return false; + } + + set_app_flow_status(CONSTELLATION_SIGN_TXN_STATUS_SEED_GENERATED); + + uint8_t serialized_txn[1024] = {0}; + size_t serialized_txn_len = 0; + serialize_txn( + constellation_txn_context->dag_txn, serialized_txn, &serialized_txn_len); + + uint8_t sha256_digest[SHA256_DIGEST_LENGTH] = {0}; + sha256_Raw(serialized_txn, serialized_txn_len, sha256_digest); + + char sha256_hex_str[SHA256_DIGEST_LENGTH * 2 + 1] = ""; + byte_array_to_hex_string(sha256_digest, + sizeof(sha256_digest), + sha256_hex_str, + sizeof(sha256_hex_str)); + + uint8_t sha512_digest[SHA512_DIGEST_LENGTH] = {0}; + sha512_Raw((uint8_t *)sha256_hex_str, strlen(sha256_hex_str), sha512_digest); + + HDNode hdnode = {0}; + derive_hdnode_from_path( + constellation_txn_context->init_info.derivation_path, + constellation_txn_context->init_info.derivation_path_count, + SECP256K1_NAME, + seed, + &hdnode); + + uint8_t signature[64] = {0}; + ecdsa_sign_digest( + &secp256k1, hdnode.private_key, sha512_digest, signature, NULL, NULL); + + der_signature->size = ecdsa_sig_to_der(signature, der_signature->bytes); + + memzero(serialized_txn, sizeof(serialized_txn)); + memzero(sha256_digest, sizeof(sha256_digest)); + memzero(sha512_digest, sizeof(sha512_digest)); + memzero(seed, sizeof(seed)); + memzero(&hdnode, sizeof(hdnode)); + memzero(signature, sizeof(signature)); + + return true; +} + +static bool send_signature(constellation_query_t *query, + const der_sig_t *der_signature) { + constellation_result_t result = + init_constellation_result(CONSTELLATION_RESULT_SIGN_TXN_TAG); + result.sign_txn.which_response = + CONSTELLATION_SIGN_TXN_RESPONSE_SIGNATURE_TAG; + + if (!constellation_get_query(query, CONSTELLATION_QUERY_SIGN_TXN_TAG) || + !check_which_request(query, + CONSTELLATION_SIGN_TXN_REQUEST_SIGNATURE_TAG)) { + return false; + } + + memcpy( + &result.sign_txn.signature.signature, der_signature, sizeof(der_sig_t)); + + constellation_send_result(&result); + return true; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +void constellation_sign_transaction(constellation_query_t *query) { + constellation_txn_context = (constellation_txn_context_t *)malloc( + sizeof(constellation_txn_context_t)); + memzero(constellation_txn_context, sizeof(constellation_txn_context_t)); + + der_sig_t der_signature = {0}; + + if (handle_initiate_query(query) && fetch_valid_input(query) && + get_user_verification() && sign_txn(&der_signature) && + send_signature(query, &der_signature)) { + delay_scr_init(ui_text_check_cysync, DELAY_TIME); + } + + if (constellation_txn_context) { + free(constellation_txn_context); + constellation_txn_context = NULL; + } +} \ No newline at end of file diff --git a/common/cypherock-common b/common/cypherock-common index be16ebadc..d78deaf0d 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit be16ebadc9863206f3bd216d721363f229417eaa +Subproject commit d78deaf0dae41a1134f4feb4cefbb81f47792352 diff --git a/common/proto-options/constellation/sign_txn.options b/common/proto-options/constellation/sign_txn.options index 2b221fe2d..f8df5071c 100644 --- a/common/proto-options/constellation/sign_txn.options +++ b/common/proto-options/constellation/sign_txn.options @@ -2,3 +2,9 @@ constellation.SignTxnInitiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true constellation.SignTxnInitiateRequest.derivation_path type:FT_STATIC max_count:5 fixed_length:true constellation.SignTxnSignatureResponse.signature type:FT_STATIC max_size:72 fixed_length:false + +constellation.Transaction.source type:FT_STATIC max_size:41 fixed_length:true +constellation.Transaction.destination type:FT_STATIC max_size:41 fixed_length:true +constellation.Parent.hash type:FT_STATIC max_size:65 fixed_length:true +constellation.Transaction.salt type:FT_STATIC max_size:16 fixed_length:false + diff --git a/src/constant_texts.h b/src/constant_texts.h index 6da9cc898..71d7de5ca 100644 --- a/src/constant_texts.h +++ b/src/constant_texts.h @@ -56,6 +56,7 @@ #define UI_TEXT_PIN "PIN\n %s" #define UI_TEXT_VERIFY_DESTINATION_TAG "Verify Destination Tag\n%lu" #define UI_TEXT_VERIFY_PRIORITY_FEE "Verify Priority Fee\n%s\n%s" +#define UI_TEXT_VERIFY_FEE "Verify Fee\n%s\n%s" // product hash extern const char *product_hash; From 140c0899357acb369b1d495edfaa33b64d9b8eb3 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Mon, 17 Mar 2025 18:40:12 +0530 Subject: [PATCH 09/75] fix: Generalized constellation sign txn --- apps/constellation_app/constellation_priv.h | 2 +- apps/constellation_app/constellation_txn.c | 18 ++++++++---------- common/cypherock-common | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/apps/constellation_app/constellation_priv.h b/apps/constellation_app/constellation_priv.h index 8bc10482a..2e3cb95c1 100644 --- a/apps/constellation_app/constellation_priv.h +++ b/apps/constellation_app/constellation_priv.h @@ -28,7 +28,7 @@ typedef struct { */ constellation_sign_txn_initiate_request_t init_info; - const constellation_transaction_t *dag_txn; + const constellation_transaction_t *txn; } constellation_txn_context_t; diff --git a/apps/constellation_app/constellation_txn.c b/apps/constellation_app/constellation_txn.c index 7e9ecd1ad..3dd9b9b23 100644 --- a/apps/constellation_app/constellation_txn.c +++ b/apps/constellation_app/constellation_txn.c @@ -291,11 +291,11 @@ static bool fetch_valid_input(constellation_query_t *query) { const constellation_sign_txn_data_t *sign_txn_data = &query->sign_txn.txn_data; - if (sign_txn_data->has_dag_txn == false) { + if (sign_txn_data->has_txn == false) { return false; } - constellation_txn_context->dag_txn = &sign_txn_data->dag_txn; + constellation_txn_context->txn = &sign_txn_data->txn; send_response(CONSTELLATION_SIGN_TXN_RESPONSE_UNSIGNED_TXN_ACCEPTED_TAG); @@ -303,19 +303,17 @@ static bool fetch_valid_input(constellation_query_t *query) { } static bool get_user_verification(void) { - const constellation_transaction_t *dag_txn = - constellation_txn_context->dag_txn; + const constellation_transaction_t *txn = constellation_txn_context->txn; // verify recipient address - if (!core_scroll_page(ui_text_verify_address, - dag_txn->destination, - constellation_send_error)) { + if (!core_scroll_page( + ui_text_verify_address, txn->destination, constellation_send_error)) { return false; } // verify recipient amount char amount_string[30] = {'\0'}; - double decimal_amount = (double)dag_txn->amount; + double decimal_amount = (double)txn->amount; decimal_amount *= 1e-8; snprintf(amount_string, sizeof(amount_string), "%.*g", 8, decimal_amount); @@ -332,7 +330,7 @@ static bool get_user_verification(void) { // verify fee char fee_string[30] = {'\0'}; - double decimal_fee = (double)dag_txn->fee; + double decimal_fee = (double)txn->fee; decimal_fee *= 1e-8; snprintf(fee_string, sizeof(fee_string), "%.*g", 8, decimal_fee); @@ -367,7 +365,7 @@ static bool sign_txn(der_sig_t *der_signature) { uint8_t serialized_txn[1024] = {0}; size_t serialized_txn_len = 0; serialize_txn( - constellation_txn_context->dag_txn, serialized_txn, &serialized_txn_len); + constellation_txn_context->txn, serialized_txn, &serialized_txn_len); uint8_t sha256_digest[SHA256_DIGEST_LENGTH] = {0}; sha256_Raw(serialized_txn, serialized_txn_len, sha256_digest); diff --git a/common/cypherock-common b/common/cypherock-common index d78deaf0d..0e7d09873 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit d78deaf0dae41a1134f4feb4cefbb81f47792352 +Subproject commit 0e7d0987335a1707e2ca74faed8e540dc36d059a From 29508116ad50b9a3074076769f9252e83ab6d1ec Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 18 Mar 2025 15:50:10 +0530 Subject: [PATCH 10/75] fix: Removed unit from amount and fee --- apps/constellation_app/constellation_txn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/constellation_app/constellation_txn.c b/apps/constellation_app/constellation_txn.c index 3dd9b9b23..908d25a2e 100644 --- a/apps/constellation_app/constellation_txn.c +++ b/apps/constellation_app/constellation_txn.c @@ -322,7 +322,7 @@ static bool get_user_verification(void) { sizeof(display), UI_TEXT_VERIFY_AMOUNT, amount_string, - CONSTELLATION_LUNIT); + ""); // We don't know the which transaction(coin or token and/or which token) is it, hence we don't know unit if (!core_confirmation(display, constellation_send_error)) { return false; @@ -339,7 +339,7 @@ static bool get_user_verification(void) { sizeof(fee_display), UI_TEXT_VERIFY_FEE, fee_string, - CONSTELLATION_LUNIT); + ""); if (!core_confirmation(fee_display, constellation_send_error)) { return false; From c472a6e9661d7d4ed99e7aa92287d86f24ae83c0 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 18 Mar 2025 17:17:52 +0530 Subject: [PATCH 11/75] fix: Code formatting --- apps/constellation_app/constellation_txn.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/constellation_app/constellation_txn.c b/apps/constellation_app/constellation_txn.c index 908d25a2e..716139a84 100644 --- a/apps/constellation_app/constellation_txn.c +++ b/apps/constellation_app/constellation_txn.c @@ -322,7 +322,8 @@ static bool get_user_verification(void) { sizeof(display), UI_TEXT_VERIFY_AMOUNT, amount_string, - ""); // We don't know the which transaction(coin or token and/or which token) is it, hence we don't know unit + ""); // We don't know the which transaction(coin or token and/or + // which token) is it, hence we don't know unit if (!core_confirmation(display, constellation_send_error)) { return false; @@ -335,11 +336,8 @@ static bool get_user_verification(void) { snprintf(fee_string, sizeof(fee_string), "%.*g", 8, decimal_fee); char fee_display[100] = {'\0'}; - snprintf(fee_display, - sizeof(fee_display), - UI_TEXT_VERIFY_FEE, - fee_string, - ""); + snprintf( + fee_display, sizeof(fee_display), UI_TEXT_VERIFY_FEE, fee_string, ""); if (!core_confirmation(fee_display, constellation_send_error)) { return false; From dcdb3b3461303c557e4b413960648e432f6796b1 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 19 Mar 2025 14:46:07 +0530 Subject: [PATCH 12/75] fix: Resolve review comments --- .../constellation_app/constellation_context.h | 1 + .../constellation_app/constellation_helpers.c | 90 ++++++++++++------- 2 files changed, 60 insertions(+), 31 deletions(-) diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h index 4efa19302..699258d87 100644 --- a/apps/constellation_app/constellation_context.h +++ b/apps/constellation_app/constellation_context.h @@ -34,6 +34,7 @@ #define PKCS_PREFIXED_PUBKEY_SIZE PKCS_PREFIX_SIZE + CONSTELLATION_PUB_KEY_SIZE #define SHA256_DIGEST_SIZE 32 #define BS58_ENCODED_SIZE 45 +#define CONSTELLATION_TXN_HASH_LENGTH 64 /***************************************************************************** * TYPEDEFS diff --git a/apps/constellation_app/constellation_helpers.c b/apps/constellation_app/constellation_helpers.c index 09febbb51..a15238dce 100644 --- a/apps/constellation_app/constellation_helpers.c +++ b/apps/constellation_app/constellation_helpers.c @@ -120,55 +120,81 @@ bool constellation_derivation_path_guard(const uint32_t *path, uint8_t levels) { /// Ref: // https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/transaction-v2.ts#L113 -void encode_txn(const constellation_transaction_t *txn, char *output) { +size_t encode_txn(const constellation_transaction_t *txn, char *output) { char temp[1024] = ""; char buffer[32] = ""; + size_t output_len = 0; // Parent count (always "2") strcat(temp, "2"); + output_len++; // Source address length and value - snprintf(buffer, sizeof(buffer), "%u", strlen(txn->source)); - strcat(temp, buffer); - strcat(temp, txn->source); + size_t src_length = strnlen(txn->source, CONSTELLATION_ACCOUNT_ADDRESS_SIZE); + size_t src_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", src_length); + strncat(temp, buffer, src_length_string_len); + strncat(temp, txn->source, src_length); + output_len += src_length_string_len + src_length; // Destination address length and value - snprintf(buffer, sizeof(buffer), "%u", strlen(txn->destination)); - strcat(temp, buffer); - strcat(temp, txn->destination); + size_t dest_length = + strnlen(txn->destination, CONSTELLATION_ACCOUNT_ADDRESS_SIZE); + size_t dest_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", dest_length); + strncat(temp, buffer, dest_length_string_len); + strncat(temp, txn->destination, dest_length); + output_len += dest_length_string_len + dest_length; // Amount length and value (hex string) char hex_str_amount[16] = ""; - snprintf(hex_str_amount, sizeof(hex_str_amount), "%llx", txn->amount); - snprintf(buffer, sizeof(buffer), "%u", strlen(hex_str_amount)); - strcat(temp, buffer); - strcat(temp, hex_str_amount); + size_t hex_str_amount_length = + snprintf(hex_str_amount, sizeof(hex_str_amount), "%llx", txn->amount); + size_t hex_str_amount_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", hex_str_amount_length); + strncat(temp, buffer, hex_str_amount_length_string_len); + strncat(temp, hex_str_amount, hex_str_amount_length); + output_len += hex_str_amount_length_string_len + hex_str_amount_length; // Parent hash length and value - snprintf(buffer, sizeof(buffer), "%u", strlen(txn->parent.hash)); - strcat(temp, buffer); - strcat(temp, txn->parent.hash); + size_t parent_hash_length = + strnlen(txn->parent.hash, CONSTELLATION_TXN_HASH_LENGTH); + size_t parent_hash_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", parent_hash_length); + strncat(temp, buffer, parent_hash_length_string_len); + strncat(temp, txn->parent.hash, parent_hash_length); + output_len += parent_hash_length_string_len + parent_hash_length; // Ordinal length and value char str_ordinal[32] = ""; - snprintf(str_ordinal, sizeof(str_ordinal), "%lu", txn->parent.ordinal); - snprintf(buffer, sizeof(buffer), "%u", strlen(str_ordinal)); - strcat(temp, buffer); - strcat(temp, str_ordinal); + size_t str_ordinal_length = + snprintf(str_ordinal, sizeof(str_ordinal), "%lu", txn->parent.ordinal); + size_t str_ordinal_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", str_ordinal_length); + strncat(temp, buffer, str_ordinal_length_string_len); + strncat(temp, str_ordinal, str_ordinal_length); + output_len += str_ordinal_length_string_len + str_ordinal_length; // Fee length and value char str_fee[32] = ""; - snprintf(str_fee, sizeof(str_fee), "%lu", txn->fee); - snprintf(buffer, sizeof(buffer), "%u", strlen(str_fee)); - strcat(temp, buffer); - strcat(temp, str_fee); + size_t str_fee_length = snprintf(str_fee, sizeof(str_fee), "%lu", txn->fee); + size_t str_fee_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", str_fee_length); + strncat(temp, buffer, str_fee_length_string_len); + strncat(temp, str_fee, str_fee_length); + output_len += str_fee_length_string_len + str_fee_length; // Salt length and value - snprintf(buffer, sizeof(buffer), "%u", strlen(txn->salt)); - strcat(temp, buffer); - strcat(temp, txn->salt); + size_t salt_length = strnlen(txn->salt, 16); + size_t salt_length_string_len = + snprintf(buffer, sizeof(buffer), "%u", salt_length); + strncat(temp, buffer, salt_length_string_len); + strncat(temp, txn->salt, salt_length); + output_len += salt_length_string_len + salt_length; - strcpy(output, temp); + strncpy(output, temp, output_len); + + return output_len; } // Encode a variable-length integer (similar to utf8Length in JS) @@ -203,12 +229,15 @@ void encode_var_length(uint32_t value, uint8_t *output, size_t *out_len) { /// Ref: // https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/tx-encode.ts#L71 -void kryo_serialize(const char *msg, uint8_t *output, size_t *out_len) { +void kryo_serialize(const char *msg, + size_t msg_len, + uint8_t *output, + size_t *out_len) { uint8_t length_encoded[5] = {0}; size_t len = 0; // Prefix is "03" + utf8Length(msg length + 1) - encode_var_length(strlen(msg) + 1, length_encoded, &len); + encode_var_length(msg_len + 1, length_encoded, &len); size_t index = 0; output[index++] = 0x03; // Prefix "03" @@ -218,7 +247,6 @@ void kryo_serialize(const char *msg, uint8_t *output, size_t *out_len) { index += len; // Append msg as raw bytes - size_t msg_len = strlen(msg); memcpy(&output[index], msg, msg_len); index += msg_len; @@ -231,7 +259,7 @@ void serialize_txn(const constellation_transaction_t *txn, uint8_t *output, size_t *output_len) { char encoded_txn[1024] = ""; - encode_txn(txn, encoded_txn); + size_t encoded_txn_len = encode_txn(txn, encoded_txn); - kryo_serialize(encoded_txn, output, output_len); + kryo_serialize(encoded_txn, encoded_txn_len, output, output_len); } \ No newline at end of file From 4cde2edfa86828566703bafa0ca595021778c031 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 12 Mar 2025 18:29:26 +0530 Subject: [PATCH 13/75] feat: Added constellation blind signing --- .../constellation_app/constellation_context.h | 8 + apps/constellation_app/constellation_main.c | 4 + apps/constellation_app/constellation_priv.h | 20 + .../constellation_sign_msg.c | 520 ++++++++++++++++++ .../proto-options/constellation/core.options | 2 +- .../proto-options/constellation/error.options | 2 +- .../constellation/sign_msg.options | 4 + 7 files changed, 558 insertions(+), 2 deletions(-) create mode 100644 apps/constellation_app/constellation_sign_msg.c create mode 100644 common/proto-options/constellation/sign_msg.options diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h index 699258d87..78770c0fb 100644 --- a/apps/constellation_app/constellation_context.h +++ b/apps/constellation_app/constellation_context.h @@ -36,6 +36,14 @@ #define BS58_ENCODED_SIZE 45 #define CONSTELLATION_TXN_HASH_LENGTH 64 +/** + * TODO: update the size of msg data same as EVM_TRANSACTION_SIZE_CAP. + * Constraints : The LVGL buffer cannot handle more than 3Kb data size which + * puts a limit on how much data can be displayed on the device. Possible fix is + * to show the long messages in chunks in line with max LVGL buffer size. + */ +#define MAX_MSG_DATA_SIZE 3072 + /***************************************************************************** * TYPEDEFS *****************************************************************************/ diff --git a/apps/constellation_app/constellation_main.c b/apps/constellation_app/constellation_main.c index 07ac3c27f..3fe308d85 100644 --- a/apps/constellation_app/constellation_main.c +++ b/apps/constellation_app/constellation_main.c @@ -137,6 +137,10 @@ void constellation_main(usb_event_t usb_evt, constellation_sign_transaction(&query); break; } + case CONSTELLATION_QUERY_SIGN_MSG_TAG: { + constellation_sign_msg(&query); + break; + } default: { /* In case we ever encounter invalid query, convey to the host app */ constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, diff --git a/apps/constellation_app/constellation_priv.h b/apps/constellation_app/constellation_priv.h index 2e3cb95c1..bf64d6b32 100644 --- a/apps/constellation_app/constellation_priv.h +++ b/apps/constellation_app/constellation_priv.h @@ -16,6 +16,7 @@ #include #include +#include "constellation/sign_msg.pb.h" #include "constellation_context.h" /***************************************************************************** @@ -32,6 +33,17 @@ typedef struct { } constellation_txn_context_t; +typedef struct { + /// @brief Contains initialization data for constellation sign msg received + /// from host + constellation_sign_msg_initiate_request_t init; + + /// @brief Pointer to msg data in raw format, size from init member is + /// allocated dynamically with a max size cap of @ref MAX_MSG_DATA_SIZE + uint8_t *msg_data; + +} constellation_sign_msg_context_t; + /***************************************************************************** * EXPORTED VARIABLES *****************************************************************************/ @@ -60,4 +72,12 @@ void constellation_get_pub_keys(constellation_query_t *query); */ void constellation_sign_transaction(constellation_query_t *query); +/** + * @brief This function signs a message with or without(blind sign) + * user verification and sends the signature as a response. + * + * @param query Reference to the decoded query struct from the host app + */ +void constellation_sign_msg(constellation_query_t *query); + #endif /* CONSTELLATION_PRIV_H */ \ No newline at end of file diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c new file mode 100644 index 000000000..fe6b818b1 --- /dev/null +++ b/apps/constellation_app/constellation_sign_msg.c @@ -0,0 +1,520 @@ +/** + * @file constellation_sign_msg.c + * @author Cypherock X1 Team + * @brief Signs messages for CONSTELLATION + *derivations. + * @copyright Copyright (c) 2025 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2025 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include + +#include "coin_utils.h" +#include "constellation/sign_msg.pb.h" +#include "constellation_api.h" +#include "constellation_context.h" +#include "constellation_helpers.h" +#include "constellation_priv.h" +#include "pb_decode.h" +#include "reconstruct_wallet_flow.h" +#include "sha2.h" +#include "status_api.h" +#include "ui_core_confirm.h" +#include "ui_screens.h" +#include "wallet_list.h" +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Checks if the provided query contains expected request. + * @details The function performs the check on the request type and if the check + * fails, then it will send an error to the host CONSTELLATION app and return + * false. + * + * @param query Reference to an instance of constellation_query_t containing + * query received from host app + * @param which_request The expected request type enum + * + * @return bool Indicating if the check succeeded or failed + * @retval true If the query contains the expected request + * @retval false If the query does not contain the expected request + */ +static bool check_which_request(const constellation_query_t *query, + pb_size_t which_request); + +/** + * @brief The function checks if the given `init_req` is a valid request for + * message signing and returns true if it is, otherwise it returns false and + * sends an error message to host. + * + * @param init_req A pointer to a structure of type + * `constellation_sign_msg_initiate_request_t`. + * + * @return a boolean value indicating init_req is valid or not. + */ +static bool validate_initiate_query( + constellation_sign_msg_initiate_request_t *init_req); + +/** + * @brief The function handles the initiation of a query to sign a message for a + * specific wallet. + * @details It performs the following tasks in response to a valid initiate + * request. + * - Get user confirmation on the wallet and coin for which flow is requested. + * - Copy the init request data to sign_msg_ctx. + * + * @param query Reference to the decoded query struct from the host app + * + * @return a boolean value. + */ +static bool handle_initiate_query(constellation_query_t *query); + +/** + * @brief This function is responsible for retrieving and assembling message + * data chunks for signing. + * + * @param query Reference to the decoded query struct from the host app + * + * @return a boolean value indicating if the message data has been reconstructed + * from chunks correctly or not. + */ +static bool get_msg_data(constellation_query_t *query); + +/** + * @brief This function displays the message for verification in case of + * verified sign. + * + * @return a boolean indicating user verification or the rejection. + */ +static bool get_user_verification(); + +/** + * @brief This function generates a signature for a message using a given + * derivation path and private key. + * + * @param sig The parameter `sig` is a pointer to a structure of type + * `constellation_sign_msg_signature_response_t`. + * + * @return a boolean value indicating if signautre for msg data is generated + * correctly or not. + */ +static bool get_msg_data_signature( + constellation_sign_msg_signature_response_t *sig); + +/** + * @brief This function sends a signature response for a sign message query. + * + * @param query A pointer to an constellation_query_t struct, which contains + * information about the query being processed. + * @param sig The parameter `sig` is of type + * `constellation_sign_msg_signature_response_t`, which is a structure + * containing the signature response for a sign message request. + * + * @return a boolean value indicating if the signature is sent to the host + * correctly or not. + */ +static bool send_signature(constellation_query_t *query, + constellation_sign_msg_signature_response_t *sig); +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ +static constellation_sign_msg_context_t sign_msg_ctx; + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +static bool check_which_request(const constellation_query_t *query, + pb_size_t which_request) { + if (which_request != query->get_public_keys.which_request) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + return true; +} + +static bool validate_initiate_query( + constellation_sign_msg_initiate_request_t *init_req) { + bool status = false; + + if (constellation_derivation_path_guard(init_req->derivation_path, + init_req->derivation_path_count)) { + status = true; + } + + // TODO: Replace macro with EVM_TRANSACTION_SIZE_CAP upon fixing the issue + // with double allocation of typed data + uint32_t size_limit = MAX_MSG_DATA_SIZE; + if (size_limit >= init_req->message_size) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + status = true; + } + + if (!status) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + return false; + } + + return true; +} + +static bool handle_initiate_query(constellation_query_t *query) { + char msg[100] = ""; + uint8_t wallet_name[NAME_SIZE] = {0}; + constellation_result_t response = + init_constellation_result(CONSTELLATION_RESULT_SIGN_MSG_TAG); + if (!check_which_request(query, + CONSTELLATION_SIGN_MSG_REQUEST_INITIATE_TAG) || + !validate_initiate_query(&query->sign_msg.initiate) || + !get_wallet_name_by_id(query->sign_msg.initiate.wallet_id, + (uint8_t *)wallet_name, + constellation_send_error)) { + return false; + } + + switch (query->sign_msg.initiate.message_type) { + case CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_MSG: { + snprintf(msg, + sizeof(msg), + "Sign message on %s from %s", + CONSTELLATION_NAME, + wallet_name); + + if (!core_confirmation(msg, constellation_send_error)) { + return false; + } + break; + } + + case CONSTELLATION_SIGN_MSG_TYPE_SIGN_ARBITRARY_DATA: { + snprintf(msg, + sizeof(msg), + "Sign data on %s from %s", + CONSTELLATION_NAME, + wallet_name); + + if (!core_confirmation(msg, constellation_send_error)) { + return false; + } + break; + } + + default: { + if (!core_confirmation(UI_TEXT_BLIND_SIGNING_WARNING, + constellation_send_error)) { + return false; + } + break; + } + } + + set_app_flow_status(CONSTELLATION_SIGN_MSG_STATUS_CONFIRM); + + memcpy(&(sign_msg_ctx.init), + &(query->sign_msg.initiate), + sizeof(query->sign_msg.initiate)); + + response.sign_msg.which_response = + CONSTELLATION_SIGN_MSG_RESPONSE_CONFIRMATION_TAG; + response.sign_msg.confirmation.dummy_field = 0; + constellation_send_result(&response); + + return true; +} + +static bool get_msg_data(constellation_query_t *query) { + constellation_result_t response = + init_constellation_result(CONSTELLATION_RESULT_SIGN_MSG_TAG); + uint32_t total_size = sign_msg_ctx.init.message_size; + const constellation_sign_msg_data_t *msg_data = &query->sign_msg.msg_data; + const common_chunk_payload_t *payload = &(msg_data->chunk_payload); + const common_chunk_payload_chunk_t *chunk = &(payload->chunk); + + uint32_t size = 0; + + /** + * Allocate required memory for message size +1. Extra byte is used to add a + * NULL character at the end of the msg data in case it'll be used as a string + */ + sign_msg_ctx.msg_data = malloc(total_size + 1); + ASSERT(NULL != sign_msg_ctx.msg_data); + sign_msg_ctx.msg_data[total_size] = '\0'; + + while (1) { + // Get next data chunk from host + if (!constellation_get_query(query, CONSTELLATION_QUERY_SIGN_MSG_TAG) || + !check_which_request(query, + CONSTELLATION_SIGN_MSG_REQUEST_MSG_DATA_TAG)) { + return false; + } + + if (false == query->sign_msg.msg_data.has_chunk_payload || + payload->chunk_index >= payload->total_chunks || + size + chunk->size > total_size) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + return false; + } + + memcpy(sign_msg_ctx.msg_data + size, chunk->bytes, chunk->size); + size += chunk->size; + + // Send chunk ack to host + response.sign_msg.which_response = + CONSTELLATION_SIGN_MSG_RESPONSE_DATA_ACCEPTED_TAG; + response.sign_msg.data_accepted.has_chunk_ack = true; + response.sign_msg.data_accepted.chunk_ack.chunk_index = + payload->chunk_index; + constellation_send_result(&response); + + // If no data remaining to be received from the host, then exit + if (0 == payload->remaining_size || + payload->chunk_index + 1 == payload->total_chunks) { + break; + } + } + + if (total_size != size) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + return false; + } + + // if (CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_DATA == + // sign_msg_ctx.init.message_type) { + // pb_istream_t istream = + // pb_istream_from_buffer(sign_msg_ctx.msg_data, total_size); + // bool result = pb_decode(&istream, + // CONSTELLATION_SIGN_TYPED_DATA_STRUCT_FIELDS, + // &(sign_msg_ctx.typed_data)); + + // if (!result) { + // constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + // ERROR_DATA_FLOW_INVALID_DATA); + // return false; + // } + // } + + return true; +} + +static bool get_user_verification() { + bool result = false; + switch (sign_msg_ctx.init.message_type) { + case CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_MSG: { + break; + } + + case CONSTELLATION_SIGN_MSG_TYPE_SIGN_ARBITRARY_DATA: { + // TODO: Add a limit on size of data per confirmation based on LVGL buffer + // and split message into multiple confirmations accordingly + break; + } + + default: { + result = core_scroll_page(UI_TEXT_VERIFY_MESSAGE, + (const char *)sign_msg_ctx.msg_data, + constellation_send_error); + break; + } + } + + if (result) { + set_app_flow_status(CONSTELLATION_SIGN_MSG_STATUS_VERIFY); + } + + return result; +} + +bool constellation_get_msg_data_digest( + const constellation_sign_msg_context_t *ctx, + uint8_t *digest) { + bool result = false; + + switch (ctx->init.message_type) { + case CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_MSG: + case CONSTELLATION_SIGN_MSG_TYPE_SIGN_ARBITRARY_DATA: { + break; + } + + default: { + sha512_Raw(ctx->msg_data, ctx->init.message_size, digest); + result = true; + break; + } + } + + return result; +} + +static bool get_msg_data_signature( + constellation_sign_msg_signature_response_t *sig) { + bool status = false; + HDNode node = {0}; + uint8_t buffer[64] = {0}; + const size_t depth = sign_msg_ctx.init.derivation_path_count; + const uint32_t *hd_path = sign_msg_ctx.init.derivation_path; + const ecdsa_curve *curve = get_curve_by_name(SECP256K1_NAME)->params; + + if (!reconstruct_seed( + sign_msg_ctx.init.wallet_id, buffer, constellation_send_error)) { + memzero(buffer, sizeof(buffer)); + return status; + } + + set_app_flow_status(CONSTELLATION_SIGN_MSG_STATUS_SEED_GENERATED); + delay_scr_init(ui_text_processing, DELAY_SHORT); + + status = + derive_hdnode_from_path(hd_path, depth, SECP256K1_NAME, buffer, &node); + + // zeroise the seed + memzero(buffer, sizeof(buffer)); + if (!status) { + constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_DATA); + } else { + status = true; + uint8_t digest[SHA512_DIGEST_LENGTH] = {0}; + uint8_t signature[64] = {0}; + if (!constellation_get_msg_data_digest(&sign_msg_ctx, digest) || + (0 != ecdsa_sign_digest( + curve, node.private_key, digest, signature, NULL, NULL))) { + constellation_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, 1); + status = false; + } + sig->signature.size = ecdsa_sig_to_der(signature, sig->signature.bytes); + } + memzero(&node, sizeof(HDNode)); + return status; +} + +static bool send_signature(constellation_query_t *query, + constellation_sign_msg_signature_response_t *sig) { + constellation_result_t result = + init_constellation_result(CONSTELLATION_RESULT_SIGN_MSG_TAG); + result.sign_msg.which_response = + CONSTELLATION_SIGN_MSG_RESPONSE_SIGNATURE_TAG; + if (!constellation_get_query(query, CONSTELLATION_QUERY_SIGN_MSG_TAG) || + !check_which_request(query, + CONSTELLATION_SIGN_MSG_REQUEST_SIGNATURE_TAG)) { + return false; + } + + memcpy(&result.sign_msg.signature, + sig, + sizeof(constellation_sign_msg_signature_response_t)); + constellation_send_result(&result); + return true; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +void constellation_sign_msg(constellation_query_t *query) { + constellation_sign_msg_signature_response_t sig_resp = + CONSTELLATION_SIGN_MSG_SIGNATURE_RESPONSE_INIT_DEFAULT; + memzero(&sign_msg_ctx, sizeof(sign_msg_ctx)); + + if (handle_initiate_query(query) && get_msg_data(query) && + get_user_verification() && get_msg_data_signature(&sig_resp) && + send_signature(query, &(sig_resp))) { + delay_scr_init(ui_text_check_cysync_app, DELAY_TIME); + } + + if (NULL != sign_msg_ctx.msg_data) { + memzero(sign_msg_ctx.msg_data, sign_msg_ctx.init.message_size); + free(sign_msg_ctx.msg_data); + sign_msg_ctx.msg_data = NULL; + } + + sign_msg_ctx.init.message_size = 0; + + /** + * The tyepd data struct fields are of FT_POINTER type which means memory for + * typed data is dynamically allocated. The dynamic allocated data needs to be + * cleared before we exit the app here. + */ + // pb_release(CONSTELLATION_SIGN_TYPED_DATA_STRUCT_FIELDS, + // &(sign_msg_ctx.typed_data)); + + // Clear the dynamic allocation done for UI purposes using cy_malloc + cy_free(); +} diff --git a/common/proto-options/constellation/core.options b/common/proto-options/constellation/core.options index 7c4863400..65a4c4612 100644 --- a/common/proto-options/constellation/core.options +++ b/common/proto-options/constellation/core.options @@ -1 +1 @@ -# Options for file common/cypherock-common/proto/xrp/core.proto +# Options for file common/cypherock-common/proto/constellation/core.proto diff --git a/common/proto-options/constellation/error.options b/common/proto-options/constellation/error.options index 5847b57ec..d8b0f145a 100644 --- a/common/proto-options/constellation/error.options +++ b/common/proto-options/constellation/error.options @@ -1 +1 @@ -# Options for file common/cypherock-common/proto/xrp/error.proto +# Options for file common/cypherock-common/proto/constellation/error.proto diff --git a/common/proto-options/constellation/sign_msg.options b/common/proto-options/constellation/sign_msg.options new file mode 100644 index 000000000..a9586d289 --- /dev/null +++ b/common/proto-options/constellation/sign_msg.options @@ -0,0 +1,4 @@ +# Options for file common/cypherock-common/proto/constellation/sign_msg.proto +constellation.SignMsgInitiateRequest.wallet_id type:FT_STATIC max_size:32 fixed_length:true +constellation.SignMsgInitiateRequest.derivation_path type:FT_STATIC max_count:5 fixed_length:true +constellation.SignMsgSignatureResponse.signature type:FT_STATIC max_size:72 fixed_length:false From 7c3074ab50cb6c301b7a3955df17f13bcb443821 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Sat, 15 Mar 2025 23:49:18 +0530 Subject: [PATCH 14/75] feat: Added constellation sign msg and data --- .../constellation_app/constellation_context.h | 4 +- .../constellation_app/constellation_helpers.c | 58 +++++ .../constellation_app/constellation_helpers.h | 11 + .../constellation_sign_msg.c | 223 ++++++++++-------- src/constant_texts.h | 3 + 5 files changed, 206 insertions(+), 93 deletions(-) diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h index 78770c0fb..b81ade423 100644 --- a/apps/constellation_app/constellation_context.h +++ b/apps/constellation_app/constellation_context.h @@ -36,8 +36,10 @@ #define BS58_ENCODED_SIZE 45 #define CONSTELLATION_TXN_HASH_LENGTH 64 +#define MAX_ALLOWED_SIZE 20480 + /** - * TODO: update the size of msg data same as EVM_TRANSACTION_SIZE_CAP. + * TODO: update the size of msg data same as MAX_ALLOWED_SIZE. * Constraints : The LVGL buffer cannot handle more than 3Kb data size which * puts a limit on how much data can be displayed on the device. Possible fix is * to show the long messages in chunks in line with max LVGL buffer size. diff --git a/apps/constellation_app/constellation_helpers.c b/apps/constellation_app/constellation_helpers.c index a15238dce..310307e8a 100644 --- a/apps/constellation_app/constellation_helpers.c +++ b/apps/constellation_app/constellation_helpers.c @@ -87,6 +87,21 @@ /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ +static const unsigned char base64_table[256] = { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, + 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64}; /***************************************************************************** * GLOBAL VARIABLES @@ -262,4 +277,47 @@ void serialize_txn(const constellation_transaction_t *txn, size_t encoded_txn_len = encode_txn(txn, encoded_txn); kryo_serialize(encoded_txn, encoded_txn_len, output, output_len); +} + +char *base64_decode(const char *input, size_t input_len) { + if (input_len % 4 != 0) { + return NULL; + } + + size_t output_len = (input_len / 4) * 3; + if (input[input_len - 1] == '=') { + output_len--; + } + if (input[input_len - 2] == '=') { + output_len--; + } + + char *decoded = malloc(output_len + 1); + if (!decoded) { + return NULL; + } + + size_t i = 0; + size_t j = 0; + uint32_t buffer = 0; + int bits_collected = 0; + + for (i = 0; i < input_len; i++) { + if (input[i] == '=') { + break; + } + uint8_t value = base64_table[(unsigned char)input[i]]; + if (value == 64) { + continue; + } + + buffer = (buffer << 6) | value; + bits_collected += 6; + if (bits_collected >= 8) { + bits_collected -= 8; + decoded[j++] = (char)((buffer >> bits_collected) & 0xFF); + } + } + decoded[j] = '\0'; + return decoded; } \ No newline at end of file diff --git a/apps/constellation_app/constellation_helpers.h b/apps/constellation_app/constellation_helpers.h index 35ed11faa..b77f5f183 100644 --- a/apps/constellation_app/constellation_helpers.h +++ b/apps/constellation_app/constellation_helpers.h @@ -66,4 +66,15 @@ void serialize_txn(const constellation_transaction_t *txn, uint8_t *output, size_t *output_len); +/** + * @brief Decodes a base64 encoded string. + * + * @param[in] input Base64 encoded string + * @param[in] input_len Length of the base64 encoded input string + * + * @return Decoded string if successful + * @return NULL otherwise + */ +char *base64_decode(const char *input, size_t input_len); + #endif // CONSTELLATION_HELPERS_H \ No newline at end of file diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index fe6b818b1..af85aed2a 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -64,7 +64,9 @@ #include #include +#include "atca_helpers.h" #include "coin_utils.h" +#include "constant_texts.h" #include "constellation/sign_msg.pb.h" #include "constellation_api.h" #include "constellation_context.h" @@ -183,11 +185,47 @@ static bool get_msg_data_signature( */ static bool send_signature(constellation_query_t *query, constellation_sign_msg_signature_response_t *sig); + +/** + * @brief This function generates prefixed message/data for signing. + * + * @param ctx A pointer to a constellation_sign_msg_context_t struct, which + * contains information about the message/data to which prefixed needs to be + * added. + * @param prefix The prefix to be added to the message/data. + * @param prefixed_msg_data The buffer to hold the resultant prefixed + * message/data. + * + * @return The length of the resultant prefixed message/data. + */ + +static size_t constellation_get_prefixed_msg_data( + const constellation_sign_msg_context_t *ctx, + const char *prefix, + char *prefixed_msg_data); + +/** + * @brief This function generates message/data digest for signing by + * hashing the prefixed message/data. + * + * @param ctx A pointer to a constellation_sign_msg_context_t struct, which + * contains information about the message/data which needs to be hashed. + * @param digest The buffer to hold the hash digest. + * + * @return A boolean whether msg data digest was generated successfully or not. + */ + +static bool constellation_get_msg_data_digest( + const constellation_sign_msg_context_t *ctx, + uint8_t *digest); + /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ static constellation_sign_msg_context_t sign_msg_ctx; +static const char *sign_message_prefix = "\031Constellation Signed Message:\n"; +static const char *sign_data_prefix = "\031Constellation Signed Data:\n"; /***************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ @@ -211,20 +249,18 @@ static bool validate_initiate_query( constellation_sign_msg_initiate_request_t *init_req) { bool status = false; - if (constellation_derivation_path_guard(init_req->derivation_path, - init_req->derivation_path_count)) { - status = true; - } + status = constellation_derivation_path_guard(init_req->derivation_path, + init_req->derivation_path_count); - // TODO: Replace macro with EVM_TRANSACTION_SIZE_CAP upon fixing the issue - // with double allocation of typed data - uint32_t size_limit = MAX_MSG_DATA_SIZE; - if (size_limit >= init_req->message_size) { - constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - ERROR_DATA_FLOW_INVALID_DATA); - status = true; + uint32_t size_limit = MAX_ALLOWED_SIZE; + if (init_req->message_type == CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_MSG || + init_req->message_type == + CONSTELLATION_SIGN_MSG_TYPE_SIGN_ARBITRARY_DATA) { + size_limit = MAX_MSG_DATA_SIZE; } + status = size_limit >= init_req->message_size; + if (!status) { constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, ERROR_DATA_FLOW_INVALID_DATA); @@ -235,7 +271,6 @@ static bool validate_initiate_query( } static bool handle_initiate_query(constellation_query_t *query) { - char msg[100] = ""; uint8_t wallet_name[NAME_SIZE] = {0}; constellation_result_t response = init_constellation_result(CONSTELLATION_RESULT_SIGN_MSG_TAG); @@ -248,40 +283,17 @@ static bool handle_initiate_query(constellation_query_t *query) { return false; } - switch (query->sign_msg.initiate.message_type) { - case CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_MSG: { - snprintf(msg, - sizeof(msg), - "Sign message on %s from %s", - CONSTELLATION_NAME, - wallet_name); - - if (!core_confirmation(msg, constellation_send_error)) { - return false; - } - break; - } + char *ui_text_prompt = UI_TEXT_SIGN_MSG_PROMPT; + if (query->sign_msg.initiate.message_type == + CONSTELLATION_SIGN_MSG_TYPE_SIGN_ARBITRARY_DATA) { + ui_text_prompt = UI_TEXT_SIGN_DATA_PROMPT; + } - case CONSTELLATION_SIGN_MSG_TYPE_SIGN_ARBITRARY_DATA: { - snprintf(msg, - sizeof(msg), - "Sign data on %s from %s", - CONSTELLATION_NAME, - wallet_name); - - if (!core_confirmation(msg, constellation_send_error)) { - return false; - } - break; - } + char msg[200] = ""; + snprintf(msg, sizeof(msg), ui_text_prompt, CONSTELLATION_NAME, wallet_name); - default: { - if (!core_confirmation(UI_TEXT_BLIND_SIGNING_WARNING, - constellation_send_error)) { - return false; - } - break; - } + if (!core_confirmation(msg, constellation_send_error)) { + return false; } set_app_flow_status(CONSTELLATION_SIGN_MSG_STATUS_CONFIRM); @@ -295,6 +307,10 @@ static bool handle_initiate_query(constellation_query_t *query) { response.sign_msg.confirmation.dummy_field = 0; constellation_send_result(&response); + // show processing screen for a minimum duration (additional time will add due + // to actual processing) + delay_scr_init(ui_text_processing, DELAY_SHORT); + return true; } @@ -356,43 +372,35 @@ static bool get_msg_data(constellation_query_t *query) { return false; } - // if (CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_DATA == - // sign_msg_ctx.init.message_type) { - // pb_istream_t istream = - // pb_istream_from_buffer(sign_msg_ctx.msg_data, total_size); - // bool result = pb_decode(&istream, - // CONSTELLATION_SIGN_TYPED_DATA_STRUCT_FIELDS, - // &(sign_msg_ctx.typed_data)); - - // if (!result) { - // constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, - // ERROR_DATA_FLOW_INVALID_DATA); - // return false; - // } - // } - return true; } static bool get_user_verification() { bool result = false; + + char *ui_text_title = UI_TEXT_VERIFY_DATA; switch (sign_msg_ctx.init.message_type) { case CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_MSG: { - break; + ui_text_title = UI_TEXT_VERIFY_MESSAGE; } - case CONSTELLATION_SIGN_MSG_TYPE_SIGN_ARBITRARY_DATA: { // TODO: Add a limit on size of data per confirmation based on LVGL buffer // and split message into multiple confirmations accordingly - break; - } + char *decoded_json = base64_decode((const char *)sign_msg_ctx.msg_data, + sign_msg_ctx.init.message_size); + if (decoded_json) { + result = core_scroll_page( + ui_text_title, decoded_json, constellation_send_error); + + free(decoded_json); + decoded_json = NULL; + } + } break; default: { - result = core_scroll_page(UI_TEXT_VERIFY_MESSAGE, - (const char *)sign_msg_ctx.msg_data, - constellation_send_error); - break; - } + result = core_confirmation(UI_TEXT_BLIND_SIGNING_WARNING, + constellation_send_error); + } break; } if (result) { @@ -402,50 +410,88 @@ static bool get_user_verification() { return result; } -bool constellation_get_msg_data_digest( +static size_t constellation_get_prefixed_msg_data( const constellation_sign_msg_context_t *ctx, - uint8_t *digest) { - bool result = false; + const char *prefix, + char *prefixed_msg_data) { + size_t msg_len = ctx->init.message_size; + size_t prefix_len = strlen(prefix); + + char length_string[20] = ""; + size_t length_string_len = + snprintf(length_string, sizeof(length_string), "%zu\n", msg_len); + + size_t total_len = prefix_len + length_string_len + msg_len; + strcpy(prefixed_msg_data, prefix); + strcat(prefixed_msg_data, length_string); + strcat(prefixed_msg_data, (const char *)ctx->msg_data); + + return total_len; +} + +static bool constellation_get_msg_data_digest( + const constellation_sign_msg_context_t *ctx, + uint8_t *digest) { switch (ctx->init.message_type) { - case CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_MSG: + case CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_MSG: { + char prefixed_message[ctx->init.message_size + 100]; + size_t prefixed_message_len = constellation_get_prefixed_msg_data( + ctx, sign_message_prefix, prefixed_message); + + sha512_Raw( + (const uint8_t *)prefixed_message, prefixed_message_len, digest); + } break; + case CONSTELLATION_SIGN_MSG_TYPE_SIGN_ARBITRARY_DATA: { - break; - } + char prefixed_data[ctx->init.message_size + 100]; + size_t prefixed_data_len = constellation_get_prefixed_msg_data( + ctx, sign_data_prefix, prefixed_data); + + uint8_t sha256_digest[SHA256_DIGEST_LENGTH] = {0}; + sha256_Raw( + (const uint8_t *)prefixed_data, prefixed_data_len, sha256_digest); + + char sha256_hex_str[SHA256_DIGEST_LENGTH * 2 + 1] = ""; + byte_array_to_hex_string(sha256_digest, + sizeof(sha256_digest), + sha256_hex_str, + sizeof(sha256_hex_str)); + + sha512_Raw((uint8_t *)sha256_hex_str, strlen(sha256_hex_str), digest); + } break; default: { sha512_Raw(ctx->msg_data, ctx->init.message_size, digest); - result = true; - break; - } + } break; } - return result; + return true; } static bool get_msg_data_signature( constellation_sign_msg_signature_response_t *sig) { bool status = false; HDNode node = {0}; - uint8_t buffer[64] = {0}; + uint8_t seed[64] = {0}; const size_t depth = sign_msg_ctx.init.derivation_path_count; const uint32_t *hd_path = sign_msg_ctx.init.derivation_path; const ecdsa_curve *curve = get_curve_by_name(SECP256K1_NAME)->params; if (!reconstruct_seed( - sign_msg_ctx.init.wallet_id, buffer, constellation_send_error)) { - memzero(buffer, sizeof(buffer)); + sign_msg_ctx.init.wallet_id, seed, constellation_send_error)) { + memzero(seed, sizeof(seed)); return status; } set_app_flow_status(CONSTELLATION_SIGN_MSG_STATUS_SEED_GENERATED); delay_scr_init(ui_text_processing, DELAY_SHORT); - status = - derive_hdnode_from_path(hd_path, depth, SECP256K1_NAME, buffer, &node); + status = derive_hdnode_from_path(hd_path, depth, SECP256K1_NAME, seed, &node); // zeroise the seed - memzero(buffer, sizeof(buffer)); + memzero(seed, sizeof(seed)); + if (!status) { constellation_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, ERROR_DATA_FLOW_INVALID_DATA); @@ -461,6 +507,7 @@ static bool get_msg_data_signature( } sig->signature.size = ecdsa_sig_to_der(signature, sig->signature.bytes); } + memzero(&node, sizeof(HDNode)); return status; } @@ -507,14 +554,6 @@ void constellation_sign_msg(constellation_query_t *query) { sign_msg_ctx.init.message_size = 0; - /** - * The tyepd data struct fields are of FT_POINTER type which means memory for - * typed data is dynamically allocated. The dynamic allocated data needs to be - * cleared before we exit the app here. - */ - // pb_release(CONSTELLATION_SIGN_TYPED_DATA_STRUCT_FIELDS, - // &(sign_msg_ctx.typed_data)); - // Clear the dynamic allocation done for UI purposes using cy_malloc cy_free(); } diff --git a/src/constant_texts.h b/src/constant_texts.h index 71d7de5ca..e20d5438c 100644 --- a/src/constant_texts.h +++ b/src/constant_texts.h @@ -57,6 +57,9 @@ #define UI_TEXT_VERIFY_DESTINATION_TAG "Verify Destination Tag\n%lu" #define UI_TEXT_VERIFY_PRIORITY_FEE "Verify Priority Fee\n%s\n%s" #define UI_TEXT_VERIFY_FEE "Verify Fee\n%s\n%s" +#define UI_TEXT_VERIFY_DATA "Verify Data" +#define UI_TEXT_SIGN_MSG_PROMPT "Sign message on %s from %s" +#define UI_TEXT_SIGN_DATA_PROMPT "Sign data on %s from %s" // product hash extern const char *product_hash; From 248874ecaedea48b9e6c99ad1a0e720cf7f2c5b1 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 19 Mar 2025 17:07:39 +0530 Subject: [PATCH 15/75] fix: Resolved review comments --- .../constellation_app/constellation_context.h | 2 + .../constellation_app/constellation_helpers.c | 58 ------------------- .../constellation_app/constellation_helpers.h | 11 ---- .../constellation_sign_msg.c | 44 +++++++++----- 4 files changed, 31 insertions(+), 84 deletions(-) diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h index b81ade423..99999c4b8 100644 --- a/apps/constellation_app/constellation_context.h +++ b/apps/constellation_app/constellation_context.h @@ -35,6 +35,8 @@ #define SHA256_DIGEST_SIZE 32 #define BS58_ENCODED_SIZE 45 #define CONSTELLATION_TXN_HASH_LENGTH 64 +#define CONSTELLATION_SIGN_MSG_PREFIX_LENGTH 31 +#define CONSTELLATION_SIGN_DATA_PREFIX_LENGTH 28 #define MAX_ALLOWED_SIZE 20480 diff --git a/apps/constellation_app/constellation_helpers.c b/apps/constellation_app/constellation_helpers.c index 310307e8a..d644029a2 100644 --- a/apps/constellation_app/constellation_helpers.c +++ b/apps/constellation_app/constellation_helpers.c @@ -87,21 +87,6 @@ /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ -static const unsigned char base64_table[256] = { - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, - 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64}; /***************************************************************************** * GLOBAL VARIABLES @@ -278,46 +263,3 @@ void serialize_txn(const constellation_transaction_t *txn, kryo_serialize(encoded_txn, encoded_txn_len, output, output_len); } - -char *base64_decode(const char *input, size_t input_len) { - if (input_len % 4 != 0) { - return NULL; - } - - size_t output_len = (input_len / 4) * 3; - if (input[input_len - 1] == '=') { - output_len--; - } - if (input[input_len - 2] == '=') { - output_len--; - } - - char *decoded = malloc(output_len + 1); - if (!decoded) { - return NULL; - } - - size_t i = 0; - size_t j = 0; - uint32_t buffer = 0; - int bits_collected = 0; - - for (i = 0; i < input_len; i++) { - if (input[i] == '=') { - break; - } - uint8_t value = base64_table[(unsigned char)input[i]]; - if (value == 64) { - continue; - } - - buffer = (buffer << 6) | value; - bits_collected += 6; - if (bits_collected >= 8) { - bits_collected -= 8; - decoded[j++] = (char)((buffer >> bits_collected) & 0xFF); - } - } - decoded[j] = '\0'; - return decoded; -} \ No newline at end of file diff --git a/apps/constellation_app/constellation_helpers.h b/apps/constellation_app/constellation_helpers.h index b77f5f183..35ed11faa 100644 --- a/apps/constellation_app/constellation_helpers.h +++ b/apps/constellation_app/constellation_helpers.h @@ -66,15 +66,4 @@ void serialize_txn(const constellation_transaction_t *txn, uint8_t *output, size_t *output_len); -/** - * @brief Decodes a base64 encoded string. - * - * @param[in] input Base64 encoded string - * @param[in] input_len Length of the base64 encoded input string - * - * @return Decoded string if successful - * @return NULL otherwise - */ -char *base64_decode(const char *input, size_t input_len); - #endif // CONSTELLATION_HELPERS_H \ No newline at end of file diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index af85aed2a..85402b818 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -65,6 +65,7 @@ #include #include "atca_helpers.h" +#include "atca_status.h" #include "coin_utils.h" #include "constant_texts.h" #include "constellation/sign_msg.pb.h" @@ -202,6 +203,7 @@ static bool send_signature(constellation_query_t *query, static size_t constellation_get_prefixed_msg_data( const constellation_sign_msg_context_t *ctx, const char *prefix, + size_t prefix_len, char *prefixed_msg_data); /** @@ -226,6 +228,9 @@ static constellation_sign_msg_context_t sign_msg_ctx; static const char *sign_message_prefix = "\031Constellation Signed Message:\n"; static const char *sign_data_prefix = "\031Constellation Signed Data:\n"; + +// for atcab_base64decode defined in atca_helpers.c +uint8_t atcab_b64rules_default[4] = {'+', '/', '=', 64}; /***************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ @@ -384,16 +389,19 @@ static bool get_user_verification() { ui_text_title = UI_TEXT_VERIFY_MESSAGE; } case CONSTELLATION_SIGN_MSG_TYPE_SIGN_ARBITRARY_DATA: { - // TODO: Add a limit on size of data per confirmation based on LVGL buffer - // and split message into multiple confirmations accordingly - char *decoded_json = base64_decode((const char *)sign_msg_ctx.msg_data, - sign_msg_ctx.init.message_size); - if (decoded_json) { + uint8_t decoded_json[sign_msg_ctx.init.message_size]; + size_t decoded_json_len = sign_msg_ctx.init.message_size; + ATCA_STATUS decoding_status = + atcab_base64decode((const char *)sign_msg_ctx.msg_data, + sign_msg_ctx.init.message_size, + decoded_json, + &decoded_json_len); + + if (decoding_status == ATCA_SUCCESS) { + // TODO: Add a limit on size of data per confirmation based on LVGL + // buffer and split message into multiple confirmations accordingly result = core_scroll_page( - ui_text_title, decoded_json, constellation_send_error); - - free(decoded_json); - decoded_json = NULL; + ui_text_title, (char *)decoded_json, constellation_send_error); } } break; @@ -413,9 +421,9 @@ static bool get_user_verification() { static size_t constellation_get_prefixed_msg_data( const constellation_sign_msg_context_t *ctx, const char *prefix, + size_t prefix_len, char *prefixed_msg_data) { size_t msg_len = ctx->init.message_size; - size_t prefix_len = strlen(prefix); char length_string[20] = ""; size_t length_string_len = @@ -423,9 +431,9 @@ static size_t constellation_get_prefixed_msg_data( size_t total_len = prefix_len + length_string_len + msg_len; - strcpy(prefixed_msg_data, prefix); - strcat(prefixed_msg_data, length_string); - strcat(prefixed_msg_data, (const char *)ctx->msg_data); + strncpy(prefixed_msg_data, prefix, prefix_len); + strncat(prefixed_msg_data, length_string, length_string_len); + strncat(prefixed_msg_data, (const char *)ctx->msg_data, msg_len); return total_len; } @@ -437,7 +445,10 @@ static bool constellation_get_msg_data_digest( case CONSTELLATION_SIGN_MSG_TYPE_SIGN_TYPED_MSG: { char prefixed_message[ctx->init.message_size + 100]; size_t prefixed_message_len = constellation_get_prefixed_msg_data( - ctx, sign_message_prefix, prefixed_message); + ctx, + sign_message_prefix, + strnlen(sign_message_prefix, CONSTELLATION_SIGN_MSG_PREFIX_LENGTH), + prefixed_message); sha512_Raw( (const uint8_t *)prefixed_message, prefixed_message_len, digest); @@ -446,7 +457,10 @@ static bool constellation_get_msg_data_digest( case CONSTELLATION_SIGN_MSG_TYPE_SIGN_ARBITRARY_DATA: { char prefixed_data[ctx->init.message_size + 100]; size_t prefixed_data_len = constellation_get_prefixed_msg_data( - ctx, sign_data_prefix, prefixed_data); + ctx, + sign_data_prefix, + strnlen(sign_data_prefix, CONSTELLATION_SIGN_DATA_PREFIX_LENGTH), + prefixed_data); uint8_t sha256_digest[SHA256_DIGEST_LENGTH] = {0}; sha256_Raw( From 346843c008749ac957212039c693abb6bc8d0c28 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 19 Mar 2025 17:28:47 +0530 Subject: [PATCH 16/75] fix: Ci tests --- apps/constellation_app/constellation_sign_msg.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index 85402b818..49d75a26e 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -229,8 +229,8 @@ static constellation_sign_msg_context_t sign_msg_ctx; static const char *sign_message_prefix = "\031Constellation Signed Message:\n"; static const char *sign_data_prefix = "\031Constellation Signed Data:\n"; -// for atcab_base64decode defined in atca_helpers.c -uint8_t atcab_b64rules_default[4] = {'+', '/', '=', 64}; +// for atcab_base64decode_ defined in atca_helpers.c as the original default is conditionally defined +uint8_t atcab_b64rules[4] = {'+', '/', '=', 64}; /***************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ @@ -392,10 +392,11 @@ static bool get_user_verification() { uint8_t decoded_json[sign_msg_ctx.init.message_size]; size_t decoded_json_len = sign_msg_ctx.init.message_size; ATCA_STATUS decoding_status = - atcab_base64decode((const char *)sign_msg_ctx.msg_data, + atcab_base64decode_((const char *)sign_msg_ctx.msg_data, sign_msg_ctx.init.message_size, decoded_json, - &decoded_json_len); + &decoded_json_len, + atcab_b64rules); if (decoding_status == ATCA_SUCCESS) { // TODO: Add a limit on size of data per confirmation based on LVGL From 26e3fe654dfc4ef340b78123f39ae35392cace97 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 19 Mar 2025 17:31:00 +0530 Subject: [PATCH 17/75] fix: Code formatting --- apps/constellation_app/constellation_sign_msg.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index 49d75a26e..b0ec153b8 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -229,7 +229,8 @@ static constellation_sign_msg_context_t sign_msg_ctx; static const char *sign_message_prefix = "\031Constellation Signed Message:\n"; static const char *sign_data_prefix = "\031Constellation Signed Data:\n"; -// for atcab_base64decode_ defined in atca_helpers.c as the original default is conditionally defined +// for atcab_base64decode_ defined in atca_helpers.c as the original default is +// conditionally defined uint8_t atcab_b64rules[4] = {'+', '/', '=', 64}; /***************************************************************************** * GLOBAL VARIABLES @@ -393,10 +394,10 @@ static bool get_user_verification() { size_t decoded_json_len = sign_msg_ctx.init.message_size; ATCA_STATUS decoding_status = atcab_base64decode_((const char *)sign_msg_ctx.msg_data, - sign_msg_ctx.init.message_size, - decoded_json, - &decoded_json_len, - atcab_b64rules); + sign_msg_ctx.init.message_size, + decoded_json, + &decoded_json_len, + atcab_b64rules); if (decoding_status == ATCA_SUCCESS) { // TODO: Add a limit on size of data per confirmation based on LVGL From 5a29ae9fde36562cb925681d5d6909ccbf145b4d Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 12 Mar 2025 18:29:26 +0530 Subject: [PATCH 18/75] feat: Added constellation blind signing --- apps/constellation_app/constellation_sign_msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index b0ec153b8..31457378d 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -523,7 +523,7 @@ static bool get_msg_data_signature( } sig->signature.size = ecdsa_sig_to_der(signature, sig->signature.bytes); } - + memzero(&node, sizeof(HDNode)); return status; } From 1fc5b4a50228316d60b80f6f96016b5d3e8e0b5a Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Sat, 15 Mar 2025 23:49:18 +0530 Subject: [PATCH 19/75] feat: Added constellation sign msg and data --- apps/constellation_app/constellation_context.h | 2 ++ apps/constellation_app/constellation_helpers.c | 15 +++++++++++++++ apps/constellation_app/constellation_helpers.h | 11 +++++++++++ 3 files changed, 28 insertions(+) diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h index 99999c4b8..e1fe4d8dd 100644 --- a/apps/constellation_app/constellation_context.h +++ b/apps/constellation_app/constellation_context.h @@ -40,6 +40,8 @@ #define MAX_ALLOWED_SIZE 20480 +#define MAX_ALLOWED_SIZE 20480 + /** * TODO: update the size of msg data same as MAX_ALLOWED_SIZE. * Constraints : The LVGL buffer cannot handle more than 3Kb data size which diff --git a/apps/constellation_app/constellation_helpers.c b/apps/constellation_app/constellation_helpers.c index d644029a2..cd706fdcb 100644 --- a/apps/constellation_app/constellation_helpers.c +++ b/apps/constellation_app/constellation_helpers.c @@ -87,6 +87,21 @@ /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ +static const unsigned char base64_table[256] = { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, + 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64}; /***************************************************************************** * GLOBAL VARIABLES diff --git a/apps/constellation_app/constellation_helpers.h b/apps/constellation_app/constellation_helpers.h index 35ed11faa..b77f5f183 100644 --- a/apps/constellation_app/constellation_helpers.h +++ b/apps/constellation_app/constellation_helpers.h @@ -66,4 +66,15 @@ void serialize_txn(const constellation_transaction_t *txn, uint8_t *output, size_t *output_len); +/** + * @brief Decodes a base64 encoded string. + * + * @param[in] input Base64 encoded string + * @param[in] input_len Length of the base64 encoded input string + * + * @return Decoded string if successful + * @return NULL otherwise + */ +char *base64_decode(const char *input, size_t input_len); + #endif // CONSTELLATION_HELPERS_H \ No newline at end of file From 26be9b9ba28ff151da71e5ae309ebaf007a6911f Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 18 Mar 2025 17:14:10 +0530 Subject: [PATCH 20/75] feat: Modified ending text of constellation --- apps/constellation_app/constellation_pub_key.c | 2 +- apps/constellation_app/constellation_sign_msg.c | 2 +- apps/constellation_app/constellation_txn.c | 2 +- src/constant_texts.c | 2 ++ src/constant_texts.h | 1 + 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/constellation_app/constellation_pub_key.c b/apps/constellation_app/constellation_pub_key.c index 3d745d8bd..b8d89f405 100644 --- a/apps/constellation_app/constellation_pub_key.c +++ b/apps/constellation_app/constellation_pub_key.c @@ -512,5 +512,5 @@ void constellation_get_pub_keys(constellation_query_t *query) { return; } - delay_scr_init(ui_text_check_cysync_app, DELAY_TIME); + delay_scr_init(ui_text_check_software_wallet_app, DELAY_TIME); } diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index 31457378d..2c83f6f41 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -559,7 +559,7 @@ void constellation_sign_msg(constellation_query_t *query) { if (handle_initiate_query(query) && get_msg_data(query) && get_user_verification() && get_msg_data_signature(&sig_resp) && send_signature(query, &(sig_resp))) { - delay_scr_init(ui_text_check_cysync_app, DELAY_TIME); + delay_scr_init(ui_text_check_software_wallet_app, DELAY_TIME); } if (NULL != sign_msg_ctx.msg_data) { diff --git a/apps/constellation_app/constellation_txn.c b/apps/constellation_app/constellation_txn.c index 716139a84..73bffbb87 100644 --- a/apps/constellation_app/constellation_txn.c +++ b/apps/constellation_app/constellation_txn.c @@ -435,7 +435,7 @@ void constellation_sign_transaction(constellation_query_t *query) { if (handle_initiate_query(query) && fetch_valid_input(query) && get_user_verification() && sign_txn(&der_signature) && send_signature(query, &der_signature)) { - delay_scr_init(ui_text_check_cysync, DELAY_TIME); + delay_scr_init(ui_text_check_software_wallet_app, DELAY_TIME); } if (constellation_txn_context) { diff --git a/src/constant_texts.c b/src/constant_texts.c index 6bd79af9a..b604ea936 100644 --- a/src/constant_texts.c +++ b/src/constant_texts.c @@ -529,6 +529,8 @@ const char *ui_text_unreliable_cards = "Warning, your cards are unreliable! Contact support"; const char *ui_critical_card_health_migrate_data = "Card health is critical! Migrate to new set of cards"; +const char *ui_text_check_software_wallet_app = + "Check the Software Wallet App"; // App specific diff --git a/src/constant_texts.h b/src/constant_texts.h index e20d5438c..5a204c85a 100644 --- a/src/constant_texts.h +++ b/src/constant_texts.h @@ -378,6 +378,7 @@ extern const char *ui_text_card_detected; extern const char *ui_text_nfc_hardware_fault_detected; extern const char *ui_text_unreliable_cards; extern const char *ui_critical_card_health_migrate_data; +extern const char *ui_text_check_software_wallet_app; // App specific From e7681a1f8bd8122a6c3a2e4844c95a7c772da7aa Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 18 Mar 2025 17:32:33 +0530 Subject: [PATCH 21/75] fix: Code formatting --- src/constant_texts.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/constant_texts.c b/src/constant_texts.c index b604ea936..dc34166f3 100644 --- a/src/constant_texts.c +++ b/src/constant_texts.c @@ -529,8 +529,7 @@ const char *ui_text_unreliable_cards = "Warning, your cards are unreliable! Contact support"; const char *ui_critical_card_health_migrate_data = "Card health is critical! Migrate to new set of cards"; -const char *ui_text_check_software_wallet_app = - "Check the Software Wallet App"; +const char *ui_text_check_software_wallet_app = "Check the Software Wallet App"; // App specific From 8076fb50756004b80ac11faf1628f35ae76afe05 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 19 Mar 2025 17:41:50 +0530 Subject: [PATCH 22/75] fix: Code formatting --- apps/constellation_app/constellation_context.h | 2 -- apps/constellation_app/constellation_helpers.c | 15 --------------- apps/constellation_app/constellation_helpers.h | 11 ----------- apps/constellation_app/constellation_sign_msg.c | 1 - 4 files changed, 29 deletions(-) diff --git a/apps/constellation_app/constellation_context.h b/apps/constellation_app/constellation_context.h index e1fe4d8dd..99999c4b8 100644 --- a/apps/constellation_app/constellation_context.h +++ b/apps/constellation_app/constellation_context.h @@ -40,8 +40,6 @@ #define MAX_ALLOWED_SIZE 20480 -#define MAX_ALLOWED_SIZE 20480 - /** * TODO: update the size of msg data same as MAX_ALLOWED_SIZE. * Constraints : The LVGL buffer cannot handle more than 3Kb data size which diff --git a/apps/constellation_app/constellation_helpers.c b/apps/constellation_app/constellation_helpers.c index cd706fdcb..d644029a2 100644 --- a/apps/constellation_app/constellation_helpers.c +++ b/apps/constellation_app/constellation_helpers.c @@ -87,21 +87,6 @@ /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ -static const unsigned char base64_table[256] = { - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, - 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64}; /***************************************************************************** * GLOBAL VARIABLES diff --git a/apps/constellation_app/constellation_helpers.h b/apps/constellation_app/constellation_helpers.h index b77f5f183..35ed11faa 100644 --- a/apps/constellation_app/constellation_helpers.h +++ b/apps/constellation_app/constellation_helpers.h @@ -66,15 +66,4 @@ void serialize_txn(const constellation_transaction_t *txn, uint8_t *output, size_t *output_len); -/** - * @brief Decodes a base64 encoded string. - * - * @param[in] input Base64 encoded string - * @param[in] input_len Length of the base64 encoded input string - * - * @return Decoded string if successful - * @return NULL otherwise - */ -char *base64_decode(const char *input, size_t input_len); - #endif // CONSTELLATION_HELPERS_H \ No newline at end of file diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index 2c83f6f41..d16301a8c 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -523,7 +523,6 @@ static bool get_msg_data_signature( } sig->signature.size = ecdsa_sig_to_der(signature, sig->signature.bytes); } - memzero(&node, sizeof(HDNode)); return status; } From 989ef5049e19ee0b86cb01c1d594cdba84c4bb1a Mon Sep 17 00:00:00 2001 From: Tejasv Sharma Date: Wed, 16 Apr 2025 06:57:21 +0530 Subject: [PATCH 23/75] chore: Exchange app boilerplate --- apps/exchange_app/exchange_api.c | 199 ++++++++++++++++++ apps/exchange_app/exchange_api.h | 117 ++++++++++ apps/exchange_app/exchange_context.h | 34 +++ apps/exchange_app/exchange_main.c | 141 +++++++++++++ apps/exchange_app/exchange_main.h | 43 ++++ apps/exchange_app/exchange_priv.h | 47 +++++ common/cypherock-common | 2 +- .../exchange/get_signature.options | 1 + .../exchange/initiate_flow.options | 1 + .../exchange/store_signature.options | 1 + 10 files changed, 585 insertions(+), 1 deletion(-) create mode 100644 apps/exchange_app/exchange_api.c create mode 100644 apps/exchange_app/exchange_api.h create mode 100644 apps/exchange_app/exchange_context.h create mode 100644 apps/exchange_app/exchange_main.c create mode 100644 apps/exchange_app/exchange_main.h create mode 100644 apps/exchange_app/exchange_priv.h create mode 100644 common/proto-options/exchange/get_signature.options create mode 100644 common/proto-options/exchange/initiate_flow.options create mode 100644 common/proto-options/exchange/store_signature.options diff --git a/apps/exchange_app/exchange_api.c b/apps/exchange_app/exchange_api.c new file mode 100644 index 000000000..843cd7bdf --- /dev/null +++ b/apps/exchange_app/exchange_api.c @@ -0,0 +1,199 @@ +/** + * @file exchange_api.c + * @author Cypherock X1 Team + * @brief Defines helpers apis for Exchange app. + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "exchange_api.h" + +#include +#include + +#include "common_error.h" +#include "core_api.h" +#include "events.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ +bool decode_exchange_query(const uint8_t *data, + uint16_t data_size, + exchange_query_t *query_out) { + if (NULL == data || NULL == query_out || 0 == data_size) { + exchange_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + return false; + } + + // zeroise for safety from garbage in the query reference + memzero(query_out, sizeof(exchange_query_t)); + + /* Create a stream that reads from the buffer. */ + pb_istream_t stream = pb_istream_from_buffer(data, data_size); + + /* Now we are ready to decode the message. */ + bool status = pb_decode(&stream, EXCHANGE_QUERY_FIELDS, query_out); + + /* Send error to host if status is false*/ + if (false == status) { + exchange_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_DECODING_FAILED); + } + + return status; +} + +bool encode_exchange_result(const exchange_result_t *result, + uint8_t *buffer, + uint16_t max_buffer_len, + size_t *bytes_written_out) { + if (NULL == result || NULL == buffer || NULL == bytes_written_out) + return false; + + /* Create a stream that will write to our buffer. */ + pb_ostream_t stream = pb_ostream_from_buffer(buffer, max_buffer_len); + + /* Now we are ready to encode the message! */ + bool status = pb_encode(&stream, EXCHANGE_RESULT_FIELDS, result); + + if (true == status) { + *bytes_written_out = stream.bytes_written; + } + + return status; +} + +bool check_exchange_query(const exchange_query_t *query, + pb_size_t exp_query_tag) { + if ((NULL == query) || (exp_query_tag != query->which_request)) { + exchange_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_QUERY); + return false; + } + return true; +} + +exchange_result_t init_exchange_result(pb_size_t result_tag) { + exchange_result_t result = EXCHANGE_RESULT_INIT_ZERO; + result.which_response = result_tag; + return result; +} + +void exchange_send_error(pb_size_t which_error, uint32_t error_code) { + exchange_result_t result = + init_exchange_result(EXCHANGE_RESULT_COMMON_ERROR_TAG); + result.common_error = init_common_error(which_error, error_code); + exchange_send_result(&result); +} + +void exchange_send_result(const exchange_result_t *result) { + // TODO: Set the options file for all + uint8_t buffer[EXCHANGE_RESULT_SIZE] = {0}; + size_t bytes_encoded = 0; + ASSERT( + encode_exchange_result(result, buffer, sizeof(buffer), &bytes_encoded)); + send_response_to_host(&buffer[0], bytes_encoded); +} + +bool exchange_get_query(exchange_query_t *query, pb_size_t exp_query_tag) { + evt_status_t event = get_events(EVENT_CONFIG_USB, MAX_INACTIVITY_TIMEOUT); + + if (true == event.p0_event.flag) { + return false; + } + + if (!decode_exchange_query( + event.usb_event.p_msg, event.usb_event.msg_size, query)) { + return false; + } + + if (!check_exchange_query(query, exp_query_tag)) { + return false; + } + + return true; +} diff --git a/apps/exchange_app/exchange_api.h b/apps/exchange_app/exchange_api.h new file mode 100644 index 000000000..c5bbaf3e4 --- /dev/null +++ b/apps/exchange_app/exchange_api.h @@ -0,0 +1,117 @@ +/** + * @file exchange_api.h + * @author Cypherock X1 Team + * @brief Header file to export some helper functions for the EXCHANGE app + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef EXCHANGE_API_H +#define EXCHANGE_API_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include +#include + +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief API to decode query from host with `EXCHANGE_QUERY_FIELDS` + * + * @param[in] data: PB encoded bytestream received from host + * @param[in] data_size: size of pb encoded bytestream + * @param[out] query_out: @ref exchange_query_t obj to copy the decoded + * result to + * @return bool True if decoding was successful, else false + */ +bool decode_exchange_query(const uint8_t *data, + uint16_t data_size, + exchange_query_t *query_out); + +/** + * @brief Encodes the EXCHANGE result with `EXCHANGE_RESULT_FIELDS` to + * byte-stream + * + * @param[in] result: object of populated @ref exchange_result_t to be + * encoded + * @param[out] buffer: buffer to fill byte-stream into + * @param[in] max_buffer_len: Max length allowed for writing bytestream to + * buffer + * @param[out] bytes_written_out: bytes written to bytestream + * @return bool True if decoding was successful, else false + */ +bool encode_exchange_result(const exchange_result_t *result, + uint8_t *buffer, + uint16_t max_buffer_len, + size_t *bytes_written_out); + +/** + * @brief This API checks if the `which_request` field of the query of type + * `exchange_query_t` matches against the expected tag. + * + * @param query The query of type `exchange_query_t` to be checked + * @param exp_query_tag The expected tag of the query + * @return true If the query tag matches the expected tag + * @return false If the query tag does not match the expected tag + */ +bool check_exchange_query(const exchange_query_t *query, + pb_size_t exp_query_tag); + +/** + * @brief Returns zero initialized object of type + * exchange_result_t result_tag set in result.which_response field + * + * @param result_tag Result tag to be set in the exchange_result_t result + * @return exchange_result_t Result object of type exchange_result_t + */ +exchange_result_t init_exchange_result(pb_size_t result_tag); + +/** + * @brief Send the error to the host. + * + * @param which_error The error type to be sent + * @param error_code The error code to sent to the host + */ +void exchange_send_error(pb_size_t which_error, uint32_t error_code); + +/** + * @brief This API encodes exchange_result_t in protobuf structure. + * @details If the encoding is successful, then it sends the corresponding + * result to the host. + * + * The function ASSERTs the result of encode_exchange_result internally. + * + * @param result The result which needs to be sent to the host. + */ +void exchange_send_result(const exchange_result_t *result); + +/** + * @brief This API receives request of type exchange_query_t of type + * exp_query_tag from the host. + * + * @param query The reference to which the query needs to be populated + * @param exp_query_tag The expected tag of the query + * @return true If the query was recieved from the host matching the tag + * @return false If the request timed out or the recieved request did not match + * the tag + */ +bool exchange_get_query(exchange_query_t *query, pb_size_t exp_query_tag); + +#endif diff --git a/apps/exchange_app/exchange_context.h b/apps/exchange_app/exchange_context.h new file mode 100644 index 000000000..d05a0b6a7 --- /dev/null +++ b/apps/exchange_app/exchange_context.h @@ -0,0 +1,34 @@ +/** + * @file exchange_context.h + * @author Cypherock X1 Team + * @brief Header file defining typedefs and MACROS for the EXCHANGE app + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef EXCHANGE_CONTEXT_H +#define EXCHANGE_CONTEXT_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ +#include +#include + +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +#endif /* EXCHANGE_CONTEXT_H */ diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c new file mode 100644 index 000000000..19733ceaf --- /dev/null +++ b/apps/exchange_app/exchange_main.c @@ -0,0 +1,141 @@ +/** + * @file exchange_main.c + * @author Cypherock X1 Team + * @brief A common entry point to various Exchange actions supported. + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "exchange_main.h" + +#include "exchange/core.pb.h" +#include "exchange_api.h" +#include "exchange_priv.h" +#include "status_api.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ +/** + * @brief Entry point for the EXCHANGE application of the X1 vault. It is + * invoked by the X1 vault firmware, as soon as there is a USB request raised + * for the Exchange app. + * + * @param usb_evt The USB event which triggered invocation of the exchange + * app + */ +void exchange_main(usb_event_t usb_evt, const void *app_config); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ +static const cy_app_desc_t exchange_app_desc = {.id = 24, + .version = + { + .major = 1, + .minor = 0, + .patch = 0, + }, + .app = exchange_main, + .app_config = NULL}; + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ +void exchange_main(usb_event_t usb_evt, const void *app_config) { + exchange_query_t query = EXCHANGE_QUERY_INIT_DEFAULT; + + if (false == decode_exchange_query(usb_evt.p_msg, usb_evt.msg_size, &query)) { + return; + } + + /* Set status to CORE_DEVICE_IDLE_STATE_USB to indicate host that we are now + * servicing a USB initiated command */ + core_status_set_idle_state(CORE_DEVICE_IDLE_STATE_USB); + + LOG_SWV("%s (%d) - Query:%d\n", __func__, __LINE__, query.which_request); + switch ((uint8_t)query.which_request) { + default: { + /* In case we ever encounter invalid query, convey to the host app */ + exchange_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_QUERY); + } break; + } +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ +const cy_app_desc_t *get_exchange_app_desc() { + return &exchange_app_desc; +} diff --git a/apps/exchange_app/exchange_main.h b/apps/exchange_app/exchange_main.h new file mode 100644 index 000000000..0e7ba116f --- /dev/null +++ b/apps/exchange_app/exchange_main.h @@ -0,0 +1,43 @@ +/** + * @file exchange_main.h + * @author Cypherock X1 Team + * @brief Header file for a common entry point to various Exchange actions + supported. + * @details + + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + */ + +#ifndef EXCHANGE_MAIN_H +#define EXCHANGE_MAIN_H + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "app_registry.h" +/***************************************************************************** + * MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ +/** + * @brief Returns the config for Exchange chain app descriptors + * + * @return A const reference to cy_app_desc_t + */ +const cy_app_desc_t *get_exchange_app_desc(); +#endif /* EXCHANGE_MAIN_H */ diff --git a/apps/exchange_app/exchange_priv.h b/apps/exchange_app/exchange_priv.h new file mode 100644 index 000000000..736f7d3b2 --- /dev/null +++ b/apps/exchange_app/exchange_priv.h @@ -0,0 +1,47 @@ +/** + * @file exchange_priv.h + * @author Cypherock X1 Team + * @brief Support for exchange app internal operations + * This file is defined to separate EXCHANGE's internal use + * functions, flows, common APIs + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ +#ifndef EXCHANGE_PRIV_H +#define EXCHANGE_PRIV_H +/***************************************************************************** + * INCLUDES + *****************************************************************************/ +#include + +#include "card_fetch_data.h" +#include "ed25519.h" +#include "exchange/core.pb.h" +#include "exchange_context.h" +#include "ui_input_text.h" +#include "wallet.h" + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ +#pragma pack(push, 1) +#pragma pack(pop) + +/***************************************************************************** + * TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * EXPORTED VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + *****************************************************************************/ + +#endif diff --git a/common/cypherock-common b/common/cypherock-common index 55f0d2739..9551655dc 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit 55f0d2739ba9d98e82a5684c0c8b509e32671046 +Subproject commit 9551655dcb596958e54156633a3791a7d7d6d6fe diff --git a/common/proto-options/exchange/get_signature.options b/common/proto-options/exchange/get_signature.options new file mode 100644 index 000000000..d737329fb --- /dev/null +++ b/common/proto-options/exchange/get_signature.options @@ -0,0 +1 @@ +exchange.GetSignatureResultResponse.signature type:FT_STATIC max_size:32 fixed_length:true diff --git a/common/proto-options/exchange/initiate_flow.options b/common/proto-options/exchange/initiate_flow.options new file mode 100644 index 000000000..047ddfe85 --- /dev/null +++ b/common/proto-options/exchange/initiate_flow.options @@ -0,0 +1 @@ +exchange.CoinDetails.wallet_id type:FT_STATIC max_size:32 fixed_length:true diff --git a/common/proto-options/exchange/store_signature.options b/common/proto-options/exchange/store_signature.options new file mode 100644 index 000000000..353b0902a --- /dev/null +++ b/common/proto-options/exchange/store_signature.options @@ -0,0 +1 @@ +exchange.StoreSignatureIntiateRequest.signature type:FT_STATIC max_size:32 fixed_length:true From d328e767f979bb8a6148f191517e7d9c57caa5a2 Mon Sep 17 00:00:00 2001 From: Tejasv Sharma Date: Thu, 17 Apr 2025 15:23:28 +0530 Subject: [PATCH 24/75] feat: Basic interaction with sdk --- apps/exchange_app/exchange_get_signature.c | 152 +++++++++++++++++++ apps/exchange_app/exchange_initiate_flow.c | 139 +++++++++++++++++ apps/exchange_app/exchange_main.c | 12 ++ apps/exchange_app/exchange_priv.h | 12 +- apps/exchange_app/exchange_store_signature.c | 139 +++++++++++++++++ common/core/app_registry.h | 2 +- common/core/core_flow_init.c | 2 + common/cypherock-common | 2 +- utilities/cmake/firmware/firmware.cmake | 2 +- utilities/cmake/simulator/simulator.cmake | 1 + 10 files changed, 454 insertions(+), 9 deletions(-) create mode 100644 apps/exchange_app/exchange_get_signature.c create mode 100644 apps/exchange_app/exchange_initiate_flow.c create mode 100644 apps/exchange_app/exchange_store_signature.c diff --git a/apps/exchange_app/exchange_get_signature.c b/apps/exchange_app/exchange_get_signature.c new file mode 100644 index 000000000..a1e72afcb --- /dev/null +++ b/apps/exchange_app/exchange_get_signature.c @@ -0,0 +1,152 @@ +/** + * @file get_signature.c + * @author Cypherock X1 Team + * @brief Dumps stored signature from shared_context to the host + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "common_error.h" +#include "exchange/get_signature.pb.h" +#include "exchange_api.h" +#include "flash_api.h" +#include "onboarding.h" +#include "status_api.h" +#include "ui_core_confirm.h" +#include "ui_screens.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Checks if the provided query contains expected request. + * @details The function performs the check on the request type and if the check + * fails, then it will send an error to the host exchange app and return false. + * + * @param query Reference to an instance of exchange_query_t containing query + * received from host app + * @param which_request The expected request type enum + * + * @return bool Indicating if the check succeeded or failed + * @retval true If the query contains the expected request + * @retval false If the query does not contain the expected request + */ +static bool check_which_request(const exchange_query_t *query, + pb_size_t which_request); + +static bool send_signature(exchange_query_t *query, exchange_result_t *result); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +static bool check_which_request(const exchange_query_t *query, + pb_size_t which_request) { + if (which_request != query->get_signature.which_request) { + exchange_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + return true; +} + +static bool send_signature(exchange_query_t *query, exchange_result_t *result) { + exchange_send_result(result); + return true; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +void exchange_get_signature(exchange_query_t *query) { + exchange_result_t result = + init_exchange_result(EXCHANGE_RESULT_GET_SIGNATURE_TAG); + if (!check_which_request(query, + EXCHANGE_GET_SIGNATURE_REQUEST_INITIATE_TAG)) { + return; + } + + result.get_signature.which_response = + EXCHANGE_GET_SIGNATURE_RESPONSE_RESULT_TAG; + + if (send_signature(query, &result) == false) { + // TODO: handle signature export failed + } +} diff --git a/apps/exchange_app/exchange_initiate_flow.c b/apps/exchange_app/exchange_initiate_flow.c new file mode 100644 index 000000000..b1d4abb64 --- /dev/null +++ b/apps/exchange_app/exchange_initiate_flow.c @@ -0,0 +1,139 @@ +/** + * @file initiate_flow.c + * @author Cypherock X1 Team + * @brief Initiates the exhchange flow + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "exchange/initiate_flow.pb.h" +#include "exchange_api.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Checks if the provided query contains expected request. + * @details The function performs the check on the request type and if the check + * fails, then it will send an error to the host exchange app and return false. + * + * @param query Reference to an instance of exchange_query_t containing query + * received from host app + * @param which_request The expected request type enum + * + * @return bool Indicating if the check succeeded or failed + * @retval true If the query contains the expected request + * @retval false If the query does not contain the expected request + */ +static bool check_which_request(const exchange_query_t *query, + pb_size_t which_request); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +static bool check_which_request(const exchange_query_t *query, + pb_size_t which_request) { + if (which_request != query->initiate_flow.which_request) { + exchange_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + return true; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +void exchange_initiate_flow(exchange_query_t *query) { + exchange_result_t result = + init_exchange_result(EXCHANGE_RESULT_INITIATE_FLOW_TAG); + if (!check_which_request(query, + EXCHANGE_INITIATE_FLOW_REQUEST_INITIATE_TAG)) { + return; + } + + // TODO: do things here + + result.initiate_flow.which_response = + EXCHANGE_INITIATE_FLOW_RESPONSE_RESULT_TAG; + + exchange_send_result(&result); +} diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index 19733ceaf..1bd3935d8 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -125,6 +125,18 @@ void exchange_main(usb_event_t usb_evt, const void *app_config) { LOG_SWV("%s (%d) - Query:%d\n", __func__, __LINE__, query.which_request); switch ((uint8_t)query.which_request) { + case EXCHANGE_QUERY_INITIATE_FLOW_TAG: { + exchange_initiate_flow(&query); + break; + } + case EXCHANGE_QUERY_GET_SIGNATURE_TAG: { + exchange_get_signature(&query); + break; + } + case EXCHANGE_QUERY_STORE_SIGNATURE_TAG: { + exchange_store_signature(&query); + break; + } default: { /* In case we ever encounter invalid query, convey to the host app */ exchange_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, diff --git a/apps/exchange_app/exchange_priv.h b/apps/exchange_app/exchange_priv.h index 736f7d3b2..a6f800474 100644 --- a/apps/exchange_app/exchange_priv.h +++ b/apps/exchange_app/exchange_priv.h @@ -13,14 +13,8 @@ /***************************************************************************** * INCLUDES *****************************************************************************/ -#include -#include "card_fetch_data.h" -#include "ed25519.h" #include "exchange/core.pb.h" -#include "exchange_context.h" -#include "ui_input_text.h" -#include "wallet.h" /***************************************************************************** * PRIVATE MACROS AND DEFINES @@ -44,4 +38,10 @@ * GLOBAL FUNCTION PROTOTYPES *****************************************************************************/ +void exchange_initiate_flow(exchange_query_t *query); + +void exchange_get_signature(exchange_query_t *query); + +void exchange_store_signature(exchange_query_t *query); + #endif diff --git a/apps/exchange_app/exchange_store_signature.c b/apps/exchange_app/exchange_store_signature.c new file mode 100644 index 000000000..a4d81fcc1 --- /dev/null +++ b/apps/exchange_app/exchange_store_signature.c @@ -0,0 +1,139 @@ +/** + * @file store_signature.c + * @author Cypherock X1 Team + * @brief Stores the signature in the shared_context + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include "exchange/store_signature.pb.h" +#include "exchange_api.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Checks if the provided query contains expected request. + * @details The function performs the check on the request type and if the check + * fails, then it will send an error to the host exchange app and return false. + * + * @param query Reference to an instance of exchange_query_t containing query + * received from host app + * @param which_request The expected request type enum + * + * @return bool Indicating if the check succeeded or failed + * @retval true If the query contains the expected request + * @retval false If the query does not contain the expected request + */ +static bool check_which_request(const exchange_query_t *query, + pb_size_t which_request); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +static bool check_which_request(const exchange_query_t *query, + pb_size_t which_request) { + if (which_request != query->store_signature.which_request) { + exchange_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + return true; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +void exchange_store_signature(exchange_query_t *query) { + exchange_result_t result = + init_exchange_result(EXCHANGE_RESULT_STORE_SIGNATURE_TAG); + if (!check_which_request(query, + EXCHANGE_STORE_SIGNATURE_REQUEST_INITIATE_TAG)) { + return; + } + + // TODO: do things here + + result.store_signature.which_response = + EXCHANGE_STORE_SIGNATURE_RESPONSE_RESULT_TAG; + + exchange_send_result(&result); +} diff --git a/common/core/app_registry.h b/common/core/app_registry.h index fee05409a..f0fa5a938 100644 --- a/common/core/app_registry.h +++ b/common/core/app_registry.h @@ -23,7 +23,7 @@ * MACROS AND DEFINES *****************************************************************************/ -#define REGISTRY_MAX_APPS 23 +#define REGISTRY_MAX_APPS 25 /***************************************************************************** * TYPEDEFS diff --git a/common/core/core_flow_init.c b/common/core/core_flow_init.c index 4f8f97f98..2170ae48d 100644 --- a/common/core/core_flow_init.c +++ b/common/core/core_flow_init.c @@ -72,6 +72,7 @@ #include "doge_app.h" #include "eth_app.h" #include "evm_main.h" +#include "exchange_main.h" #include "fantom_app.h" #include "icp_main.h" #include "inheritance_main.h" @@ -187,4 +188,5 @@ void core_init_app_registry() { registry_add_app(get_xrp_app_desc()); registry_add_app(get_starknet_app_desc()); registry_add_app(get_icp_app_desc()); + registry_add_app(get_exchange_app_desc()); } diff --git a/common/cypherock-common b/common/cypherock-common index 9551655dc..80008c3b3 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit 9551655dcb596958e54156633a3791a7d7d6d6fe +Subproject commit 80008c3b3d249ba03515f9028de83ea55382ad2e diff --git a/utilities/cmake/firmware/firmware.cmake b/utilities/cmake/firmware/firmware.cmake index e573bea43..c5fd9ca31 100644 --- a/utilities/cmake/firmware/firmware.cmake +++ b/utilities/cmake/firmware/firmware.cmake @@ -60,9 +60,9 @@ target_include_directories(${EXECUTABLE} PRIVATE apps/tron_app apps/inheritance_app apps/starknet_app - apps/xrp_app apps/icp_app + apps/exchange_app src/ src/menu diff --git a/utilities/cmake/simulator/simulator.cmake b/utilities/cmake/simulator/simulator.cmake index 6058abc68..db73c6f4d 100644 --- a/utilities/cmake/simulator/simulator.cmake +++ b/utilities/cmake/simulator/simulator.cmake @@ -59,6 +59,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE apps/xrp_app apps/starknet_app apps/icp_app + apps/exchange_app src/ src/menu From 17ff395ed8b596e306324c08af2308625ef6a8ef Mon Sep 17 00:00:00 2001 From: Tejasv Sharma Date: Fri, 18 Apr 2025 14:13:00 +0530 Subject: [PATCH 25/75] feat: Compsable queue and shared context --- common/core/composable_app_queue.c | 91 ++++++++++++++++++++++++++++ common/core/composable_app_queue.h | 49 +++++++++++++++ common/core/core_shared_context.c | 97 ++++++++++++++++++++++++++++++ common/core/core_shared_context.h | 29 +++++++++ src/main.c | 2 + 5 files changed, 268 insertions(+) create mode 100644 common/core/composable_app_queue.c create mode 100644 common/core/composable_app_queue.h create mode 100644 common/core/core_shared_context.c create mode 100644 common/core/core_shared_context.h diff --git a/common/core/composable_app_queue.c b/common/core/composable_app_queue.c new file mode 100644 index 000000000..ad44ee713 --- /dev/null +++ b/common/core/composable_app_queue.c @@ -0,0 +1,91 @@ +/** + * @author Cypherock X1 Team + * + * @copyright Copyright (c) 2022 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ + +#include "composable_app_queue.h" + +#include +static composable_app_queue_t *composable_app_queue = NULL; + +static caq_node_t *caq_new_node(caq_node_data_t data) { + caq_node_t *temp = (caq_node_t *)malloc(sizeof(caq_node_t)); + temp->data = data; + temp->next = NULL; + return temp; +} + +static composable_app_queue_t *caq_create_queue() { + composable_app_queue_t *queue = + (composable_app_queue_t *)malloc(sizeof(composable_app_queue_t)); + queue->front = queue->rear = NULL; + queue->count = 0; + return queue; +} + +bool caq_is_empty() { + return (composable_app_queue->count == 0); +} + +void caq_push(caq_node_data_t data) { + caq_node_t *temp = caq_new_node(data); + composable_app_queue->count++; + + if (composable_app_queue->rear == NULL) { + composable_app_queue->front = composable_app_queue->rear = temp; + return; + } + + composable_app_queue->rear->next = temp; + composable_app_queue->rear = temp; +} + +bool caq_pop() { + if (caq_is_empty()) { + return false; + } + + caq_node_t *temp = composable_app_queue->front; + + composable_app_queue->front = composable_app_queue->front->next; + if (composable_app_queue->front == NULL) { + composable_app_queue->rear = NULL; + } + composable_app_queue->count--; + + free(temp); + return true; +} + +caq_node_data_t caq_peek(bool *status) { + *status = false; + caq_node_data_t output = {0}; + + if (caq_is_empty()) { + return output; + } + + caq_node_t *temp = composable_app_queue->front; + + output = temp->data; + *status = true; + + return output; +} + +bool caq_clear() { + while (!caq_is_empty()) { + bool status = caq_pop(); + if (!status) { + return false; + } + } + return true; +} + +void caq_init() { + composable_app_queue = caq_create_queue(); +} diff --git a/common/core/composable_app_queue.h b/common/core/composable_app_queue.h new file mode 100644 index 000000000..072d05cc2 --- /dev/null +++ b/common/core/composable_app_queue.h @@ -0,0 +1,49 @@ +/** + * @author Cypherock X1 Team + * + * @copyright Copyright (c) 2022 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ + +#ifndef COMPOSABLE_APP_QUEUE +#define COMPOSABLE_APP_QUEUE + +#include +#pragma once + +#include + +#define APP_QUEUE_PARAMS_SIZE 128 +#define APP_QUEUE_CALLER_NAME_SIZE 32 + +typedef struct caq_node_data { + uint32_t applet_id; + uint8_t params[APP_QUEUE_PARAMS_SIZE]; + // Add a caller id here if multiple apps are using this in future +} caq_node_data_t; + +typedef struct caq_node { + caq_node_data_t data; + struct caq_node *next; +} caq_node_t; + +typedef struct composable_app_queue { + caq_node_t *front; + caq_node_t *rear; + int count; +} composable_app_queue_t; + +bool caq_is_empty(); + +void caq_push(caq_node_data_t data); + +bool caq_pop(); + +caq_node_data_t caq_peek(bool *status); + +bool caq_clear(); + +void caq_init(); + +#endif // COMPOSABLE_APP_QUEUE diff --git a/common/core/core_shared_context.c b/common/core/core_shared_context.c new file mode 100644 index 000000000..7ec499998 --- /dev/null +++ b/common/core/core_shared_context.c @@ -0,0 +1,97 @@ +/** + * @author Cypherock X1 Team + * + * @copyright Copyright (c) 2022 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2022 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ +#include "core_shared_context.h" + +#include + +#include "memzero.h" +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +uint8_t shared_context[SHARED_CONTEXT_SIZE]; + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +void core_clear_shared_context() { + memzero(shared_context, SHARED_CONTEXT_SIZE); +} diff --git a/common/core/core_shared_context.h b/common/core/core_shared_context.h new file mode 100644 index 000000000..01fc99139 --- /dev/null +++ b/common/core/core_shared_context.h @@ -0,0 +1,29 @@ +/** + * @author Cypherock X1 Team + * @brief Header file containing the session functions + * This file declares the functions used to create and manage the + * shared context. + * + * @copyright Copyright (c) 2022 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + */ + +#ifndef CORE_SHARED_CONTEXT +#define CORE_SHARED_CONTEXT + +#pragma once + +#include +#include + +#include "core.pb.h" +#include "device_authentication_api.h" + +#define SHARED_CONTEXT_SIZE 256 + +extern uint8_t shared_context[SHARED_CONTEXT_SIZE]; + +void core_clear_shared_context(); + +#endif // CORE_SHARED_CONTEXT diff --git a/src/main.c b/src/main.c index 959bab00f..6d7657007 100644 --- a/src/main.c +++ b/src/main.c @@ -76,6 +76,7 @@ */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ +#include "composable_app_queue.h" #define _DEFAULT_SOURCE /* needed for usleep() */ #include #include @@ -137,6 +138,7 @@ int main(void) { ekp_queue_init(); #endif application_init(); + caq_init(); #ifdef RUN_ENGINE #if USE_SIMULATOR == 0 From 23bbd8d38b8493bef93204053d6e2a557e4dcadf Mon Sep 17 00:00:00 2001 From: Tejasv Sharma Date: Fri, 18 Apr 2025 14:13:36 +0530 Subject: [PATCH 26/75] feat: Exchange app uses composable queue --- apps/exchange_app/exchange_context.h | 1 - apps/exchange_app/exchange_get_signature.c | 13 +++-- apps/exchange_app/exchange_initiate_flow.c | 58 +++++++++++++++++++- apps/exchange_app/exchange_main.c | 44 +++++++++++++++ apps/exchange_app/exchange_main.h | 10 ++++ apps/exchange_app/exchange_store_signature.c | 10 ++++ 6 files changed, 128 insertions(+), 8 deletions(-) diff --git a/apps/exchange_app/exchange_context.h b/apps/exchange_app/exchange_context.h index d05a0b6a7..f0a8f1915 100644 --- a/apps/exchange_app/exchange_context.h +++ b/apps/exchange_app/exchange_context.h @@ -13,7 +13,6 @@ * INCLUDES *****************************************************************************/ #include -#include /***************************************************************************** * MACROS AND DEFINES diff --git a/apps/exchange_app/exchange_get_signature.c b/apps/exchange_app/exchange_get_signature.c index a1e72afcb..60baa3003 100644 --- a/apps/exchange_app/exchange_get_signature.c +++ b/apps/exchange_app/exchange_get_signature.c @@ -60,14 +60,10 @@ * INCLUDES *****************************************************************************/ -#include "common_error.h" #include "exchange/get_signature.pb.h" #include "exchange_api.h" -#include "flash_api.h" -#include "onboarding.h" +#include "exchange_main.h" #include "status_api.h" -#include "ui_core_confirm.h" -#include "ui_screens.h" /***************************************************************************** * EXTERN VARIABLES @@ -123,6 +119,13 @@ static bool check_which_request(const exchange_query_t *query, return false; } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + data.params[0] = EXCHANGE_FLOW_TAG_FETCH_SIGNATURE; + + exchange_app_validate_caq(data); + return true; } diff --git a/apps/exchange_app/exchange_initiate_flow.c b/apps/exchange_app/exchange_initiate_flow.c index b1d4abb64..eccf54ae3 100644 --- a/apps/exchange_app/exchange_initiate_flow.c +++ b/apps/exchange_app/exchange_initiate_flow.c @@ -60,8 +60,14 @@ * INCLUDES *****************************************************************************/ +#include + +#include "composable_app_queue.h" #include "exchange/initiate_flow.pb.h" #include "exchange_api.h" +#include "exchange_context.h" +#include "exchange_main.h" +#include "memzero.h" /***************************************************************************** * EXTERN VARIABLES @@ -130,10 +136,58 @@ void exchange_initiate_flow(exchange_query_t *query) { return; } - // TODO: do things here + // Clear existing composable app queue + caq_clear(); + + // Receive flow + { + caq_node_data_t data = {.applet_id = + query->initiate_flow.initiate.to.applet_id}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + query->initiate_flow.initiate.to.wallet_id, + sizeof(query->initiate_flow.initiate.to.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; + + caq_push(data); + } + + // Fetch signature for receive address + { + caq_node_data_t data = {.applet_id = get_exchange_app_desc()->id}; + + memzero(data.params, sizeof(data.params)); + data.params[0] = EXCHANGE_FLOW_TAG_FETCH_SIGNATURE; + + caq_push(data); + } + + // Store signature for receiver address in send flow + { + caq_node_data_t data = {.applet_id = get_exchange_app_desc()->id}; + + memzero(data.params, sizeof(data.params)); + data.params[0] = EXCHANGE_FLOW_TAG_STORE_SIGNATURE; + + caq_push(data); + } + + // Send flow + { + caq_node_data_t data = {.applet_id = + query->initiate_flow.initiate.from.applet_id}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + query->initiate_flow.initiate.to.wallet_id, + sizeof(query->initiate_flow.initiate.to.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_SEND; + + caq_push(data); + } result.initiate_flow.which_response = EXCHANGE_INITIATE_FLOW_RESPONSE_RESULT_TAG; - exchange_send_result(&result); } diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index 1bd3935d8..93a984cd9 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -62,10 +62,17 @@ #include "exchange_main.h" +#include + +#include "board.h" +#include "composable_app_queue.h" #include "exchange/core.pb.h" #include "exchange_api.h" #include "exchange_priv.h" #include "status_api.h" +#include "ui_core_confirm.h" +#include "ui_delay.h" +#include "utils.h" /***************************************************************************** * EXTERN VARIABLES @@ -151,3 +158,40 @@ void exchange_main(usb_event_t usb_evt, const void *app_config) { const cy_app_desc_t *get_exchange_app_desc() { return &exchange_app_desc; } + +bool exchange_app_validate_caq(caq_node_data_t data) { + bool status = false; + caq_node_data_t caq_data = caq_peek(&status); + if (!status) { + return false; + } + + /*{*/ + /* char hex_arr[500] = {0};*/ + /* byte_array_to_hex_string(*/ + /* data.params, sizeof(data.params), hex_arr, sizeof(hex_arr));*/ + /* core_scroll_page("params", hex_arr, NULL);*/ + /*}*/ + /**/ + /*{*/ + /* char hex_arr[500] = {0};*/ + /* byte_array_to_hex_string(*/ + /* caq_data.params, sizeof(caq_data.params), hex_arr, sizeof(hex_arr));*/ + /* core_scroll_page("params", hex_arr, NULL);*/ + /*}*/ + + if (caq_data.applet_id == data.applet_id && + memcmp(caq_data.params, data.params, sizeof(data.params)) == 0) { + if (caq_data.applet_id != exchange_app_desc.id) { + delay_scr_init("Swap", DELAY_SHORT); + } + + caq_pop(); + return true; + } + + delay_scr_init("Invalid operation during Swap\n rebooting...", DELAY_TIME); + BSP_reset(); + + return false; +} diff --git a/apps/exchange_app/exchange_main.h b/apps/exchange_app/exchange_main.h index 0e7ba116f..af88e653e 100644 --- a/apps/exchange_app/exchange_main.h +++ b/apps/exchange_app/exchange_main.h @@ -19,6 +19,7 @@ *****************************************************************************/ #include "app_registry.h" +#include "composable_app_queue.h" /***************************************************************************** * MACROS AND DEFINES *****************************************************************************/ @@ -27,6 +28,13 @@ * TYPEDEFS *****************************************************************************/ +typedef enum EXCHANGE_FLOW_TAGS { + EXCHANGE_FLOW_TAG_RECEIVE = 0x1, + EXCHANGE_FLOW_TAG_FETCH_SIGNATURE, + EXCHANGE_FLOW_TAG_STORE_SIGNATURE, + EXCHANGE_FLOW_TAG_SEND, +} exchange_flow_tag_e; + /***************************************************************************** * EXPORTED VARIABLES *****************************************************************************/ @@ -40,4 +48,6 @@ * @return A const reference to cy_app_desc_t */ const cy_app_desc_t *get_exchange_app_desc(); + +bool exchange_app_validate_caq(caq_node_data_t data); #endif /* EXCHANGE_MAIN_H */ diff --git a/apps/exchange_app/exchange_store_signature.c b/apps/exchange_app/exchange_store_signature.c index a4d81fcc1..6793293e2 100644 --- a/apps/exchange_app/exchange_store_signature.c +++ b/apps/exchange_app/exchange_store_signature.c @@ -60,8 +60,11 @@ * INCLUDES *****************************************************************************/ +#include "composable_app_queue.h" #include "exchange/store_signature.pb.h" #include "exchange_api.h" +#include "exchange_main.h" +#include "status_api.h" /***************************************************************************** * EXTERN VARIABLES @@ -115,6 +118,13 @@ static bool check_which_request(const exchange_query_t *query, return false; } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + data.params[0] = EXCHANGE_FLOW_TAG_STORE_SIGNATURE; + + exchange_app_validate_caq(data); + return true; } From 2cad3ccfdceef6edd1e096ec5a29a7802b54cf4c Mon Sep 17 00:00:00 2001 From: Tejasv Sharma Date: Fri, 18 Apr 2025 14:13:58 +0530 Subject: [PATCH 27/75] feat: Validate composable queue in every coin flow --- apps/btc_family/btc_pub_key.c | 15 +++++++++++++++ apps/btc_family/btc_txn.c | 13 +++++++++++++ apps/evm_family/evm_pub_key.c | 12 ++++++++++++ apps/evm_family/evm_sign_txn.c | 15 ++++++++++++++- apps/icp_app/icp_pub_key.c | 10 ++++++++++ apps/icp_app/icp_txn.c | 13 +++++++++++++ apps/near_app/near_pub_key.c | 10 ++++++++++ apps/near_app/near_txn.c | 15 ++++++++++++++- apps/solana_app/solana_pub_key.c | 14 +++++++++++++- apps/solana_app/solana_sign_txn.c | 14 +++++++++++++- apps/starknet_app/starknet_pub_key.c | 12 ++++++++++++ apps/starknet_app/starknet_sign_txn.c | 15 ++++++++++++++- apps/tron_app/tron_pub_key.c | 14 +++++++++++++- apps/tron_app/tron_sign_txn.c | 16 ++++++++++++++-- apps/xrp_app/xrp_pub_key.c | 10 ++++++++++ apps/xrp_app/xrp_txn.c | 14 +++++++++++++- 16 files changed, 203 insertions(+), 9 deletions(-) diff --git a/apps/btc_family/btc_pub_key.c b/apps/btc_family/btc_pub_key.c index 6c56aac18..e44cfb0bd 100644 --- a/apps/btc_family/btc_pub_key.c +++ b/apps/btc_family/btc_pub_key.c @@ -60,12 +60,16 @@ * INCLUDES *****************************************************************************/ +#include + #include "bip32.h" #include "btc_api.h" #include "btc_helpers.h" #include "btc_priv.h" #include "coin_utils.h" +#include "composable_app_queue.h" #include "curves.h" +#include "exchange_main.h" #include "reconstruct_wallet_flow.h" #include "status_api.h" #include "ui_core_confirm.h" @@ -173,6 +177,17 @@ static bool validate_request_data(btc_get_public_key_request_t *request) { ERROR_DATA_FLOW_INVALID_DATA); status = false; } + + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; + + exchange_app_validate_caq(data); + return status; } diff --git a/apps/btc_family/btc_txn.c b/apps/btc_family/btc_txn.c index 570a8cf71..06380eb88 100644 --- a/apps/btc_family/btc_txn.c +++ b/apps/btc_family/btc_txn.c @@ -74,8 +74,10 @@ #include "byte_stream.h" #include "coin_utils.h" #include "common.pb.h" +#include "composable_app_queue.h" #include "constant_texts.h" #include "curves.h" +#include "exchange_main.h" #include "reconstruct_wallet_flow.h" #include "status_api.h" #include "ui_core_confirm.h" @@ -305,6 +307,17 @@ static bool validate_request_data(const btc_sign_txn_request_t *request) { ERROR_DATA_FLOW_INVALID_DATA); status = false; } + + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_SEND; + + exchange_app_validate_caq(data); + return status; } diff --git a/apps/evm_family/evm_pub_key.c b/apps/evm_family/evm_pub_key.c index 84f8cae33..134f564d5 100644 --- a/apps/evm_family/evm_pub_key.c +++ b/apps/evm_family/evm_pub_key.c @@ -64,9 +64,11 @@ #include #include "address.h" +#include "composable_app_queue.h" #include "evm_api.h" #include "evm_helpers.h" #include "evm_priv.h" +#include "exchange_main.h" #include "reconstruct_wallet_flow.h" #include "status_api.h" #include "ui_core_confirm.h" @@ -275,6 +277,16 @@ static bool validate_request_data(evm_get_public_keys_request_t *request, } } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; + + exchange_app_validate_caq(data); + return status; } diff --git a/apps/evm_family/evm_sign_txn.c b/apps/evm_family/evm_sign_txn.c index f49ee37aa..c9b5a0014 100644 --- a/apps/evm_family/evm_sign_txn.c +++ b/apps/evm_family/evm_sign_txn.c @@ -61,10 +61,12 @@ *****************************************************************************/ #include "address.h" +#include "composable_app_queue.h" #include "evm_api.h" #include "evm_helpers.h" #include "evm_priv.h" #include "evm_user_verification.h" +#include "exchange_main.h" #include "reconstruct_wallet_flow.h" #include "status_api.h" #include "ui_core_confirm.h" @@ -243,6 +245,17 @@ static bool validate_request_data(const evm_sign_txn_request_t *request) { ERROR_DATA_FLOW_INVALID_DATA); status = false; } + + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_SEND; + + exchange_app_validate_caq(data); + return status; } @@ -444,4 +457,4 @@ void evm_sign_transaction(evm_query_t *query) { free(txn_context); txn_context = NULL; } -} \ No newline at end of file +} diff --git a/apps/icp_app/icp_pub_key.c b/apps/icp_app/icp_pub_key.c index 8e0434ee2..197429560 100644 --- a/apps/icp_app/icp_pub_key.c +++ b/apps/icp_app/icp_pub_key.c @@ -65,9 +65,11 @@ #include #include "bip32.h" +#include "composable_app_queue.h" #include "constant_texts.h" #include "curves.h" #include "ecdsa.h" +#include "exchange_main.h" #include "icp/get_public_key.pb.h" #include "icp_api.h" #include "icp_context.h" @@ -262,6 +264,14 @@ static bool validate_request(const icp_get_public_keys_intiate_request_t *req, } } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, req->wallet_id, sizeof(req->wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; + + exchange_app_validate_caq(data); + return status; } diff --git a/apps/icp_app/icp_txn.c b/apps/icp_app/icp_txn.c index 648186929..d22354be4 100644 --- a/apps/icp_app/icp_txn.c +++ b/apps/icp_app/icp_txn.c @@ -67,7 +67,9 @@ #include #include "base58.h" +#include "composable_app_queue.h" #include "constant_texts.h" +#include "exchange_main.h" #include "icp/sign_txn.pb.h" #include "icp_api.h" #include "icp_context.h" @@ -268,6 +270,17 @@ static bool validate_request_data(const icp_sign_txn_request_t *request) { ERROR_DATA_FLOW_INVALID_DATA); status = false; } + + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_SEND; + + exchange_app_validate_caq(data); + return status; } diff --git a/apps/near_app/near_pub_key.c b/apps/near_app/near_pub_key.c index e6636ddde..953427bad 100644 --- a/apps/near_app/near_pub_key.c +++ b/apps/near_app/near_pub_key.c @@ -60,6 +60,8 @@ * INCLUDES *****************************************************************************/ +#include "composable_app_queue.h" +#include "exchange_main.h" #include "near_api.h" #include "near_context.h" #include "near_helpers.h" @@ -252,6 +254,14 @@ static bool validate_request(const near_get_public_keys_intiate_request_t *req, } } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, req->wallet_id, sizeof(req->wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; + + exchange_app_validate_caq(data); + return status; } diff --git a/apps/near_app/near_txn.c b/apps/near_app/near_txn.c index 43f226888..d11f3b825 100644 --- a/apps/near_app/near_txn.c +++ b/apps/near_app/near_txn.c @@ -61,6 +61,8 @@ * INCLUDES *****************************************************************************/ +#include "composable_app_queue.h" +#include "exchange_main.h" #include "near_api.h" #include "near_context.h" #include "near_helpers.h" @@ -231,6 +233,17 @@ static bool validate_request_data(const near_sign_txn_request_t *request) { ERROR_DATA_FLOW_INVALID_DATA); status = false; } + + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_SEND; + + exchange_app_validate_caq(data); + return status; } @@ -397,4 +410,4 @@ void near_sign_transaction(near_query_t *query) { } return; -} \ No newline at end of file +} diff --git a/apps/solana_app/solana_pub_key.c b/apps/solana_app/solana_pub_key.c index b4bbfdec6..970545f91 100644 --- a/apps/solana_app/solana_pub_key.c +++ b/apps/solana_app/solana_pub_key.c @@ -63,6 +63,8 @@ #include #include +#include "composable_app_queue.h" +#include "exchange_main.h" #include "reconstruct_wallet_flow.h" #include "solana_api.h" #include "solana_helpers.h" @@ -256,6 +258,16 @@ STATIC bool validate_request_data(solana_get_public_keys_request_t *request, } } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; + + exchange_app_validate_caq(data); + return status; } @@ -451,4 +463,4 @@ void solana_get_pub_keys(solana_query_t *query) { } delay_scr_init(ui_text_check_cysync_app, DELAY_TIME); -} \ No newline at end of file +} diff --git a/apps/solana_app/solana_sign_txn.c b/apps/solana_app/solana_sign_txn.c index dbda91058..0e67af8fe 100644 --- a/apps/solana_app/solana_sign_txn.c +++ b/apps/solana_app/solana_sign_txn.c @@ -62,6 +62,8 @@ #include +#include "composable_app_queue.h" +#include "exchange_main.h" #include "int-util.h" #include "reconstruct_wallet_flow.h" #include "solana_api.h" @@ -246,6 +248,16 @@ static bool validate_request_data(const solana_sign_txn_request_t *request) { status = false; } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_SEND; + + exchange_app_validate_caq(data); + return status; } @@ -812,4 +824,4 @@ void solana_sign_transaction(solana_query_t *query) { free(solana_txn_context); solana_txn_context = NULL; } -} \ No newline at end of file +} diff --git a/apps/starknet_app/starknet_pub_key.c b/apps/starknet_app/starknet_pub_key.c index 3fce53277..131a7df89 100644 --- a/apps/starknet_app/starknet_pub_key.c +++ b/apps/starknet_app/starknet_pub_key.c @@ -64,6 +64,8 @@ #include #include "assert_conf.h" +#include "composable_app_queue.h" +#include "exchange_main.h" #include "mini-gmp-helpers.h" #include "reconstruct_wallet_flow.h" #include "starkcurve.h" @@ -279,6 +281,16 @@ static bool validate_request_data(starknet_get_public_keys_request_t *request, } } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; + + exchange_app_validate_caq(data); + return status; } diff --git a/apps/starknet_app/starknet_sign_txn.c b/apps/starknet_app/starknet_sign_txn.c index d1559339a..7a708b95a 100644 --- a/apps/starknet_app/starknet_sign_txn.c +++ b/apps/starknet_app/starknet_sign_txn.c @@ -63,7 +63,9 @@ *****************************************************************************/ #include "bignum.h" +#include "composable_app_queue.h" #include "ecdsa.h" +#include "exchange_main.h" #include "mini-gmp-helpers.h" #include "mini-gmp.h" #include "mpz_ecdsa.h" @@ -254,6 +256,17 @@ static bool validate_request_data(const starknet_sign_txn_request_t *request) { ERROR_DATA_FLOW_INVALID_DATA); status = false; } + + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_SEND; + + exchange_app_validate_caq(data); + return status; } @@ -626,4 +639,4 @@ void starknet_sign_transaction(starknet_query_t *query) { } return; -} \ No newline at end of file +} diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c index 45624b045..396316410 100644 --- a/apps/tron_app/tron_pub_key.c +++ b/apps/tron_app/tron_pub_key.c @@ -66,7 +66,9 @@ #include "base58.h" #include "bip32.h" #include "coin_utils.h" +#include "composable_app_queue.h" #include "curves.h" +#include "exchange_main.h" #include "reconstruct_wallet_flow.h" #include "sha3.h" #include "status_api.h" @@ -264,6 +266,16 @@ static bool validate_request_data(tron_get_public_keys_request_t *request, } } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; + + exchange_app_validate_caq(data); + return status; } @@ -474,4 +486,4 @@ void tron_get_pub_keys(tron_query_t *query) { } delay_scr_init(ui_text_check_cysync_app, DELAY_TIME); -} \ No newline at end of file +} diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index 4e49a8b50..a8409cf28 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -69,8 +69,10 @@ #include "base58.h" #include "coin_utils.h" +#include "composable_app_queue.h" #include "curves.h" #include "ecdsa.h" +#include "exchange_main.h" #include "hasher.h" #include "reconstruct_wallet_flow.h" #include "secp256k1.h" @@ -83,7 +85,7 @@ #include "ui_core_confirm.h" #include "ui_screens.h" #include "wallet_list.h" -//#include "tron_contracts.c" +// #include "tron_contracts.c" /***************************************************************************** * EXTERN VARIABLES @@ -250,6 +252,16 @@ static bool validate_request_data(const tron_sign_txn_request_t *request) { status = false; } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_SEND; + + exchange_app_validate_caq(data); + return status; } @@ -437,4 +449,4 @@ void tron_sign_transaction(tron_query_t *query) { free(tron_txn_context); tron_txn_context = NULL; } -} \ No newline at end of file +} diff --git a/apps/xrp_app/xrp_pub_key.c b/apps/xrp_app/xrp_pub_key.c index 4b0c04b6c..99555b39a 100644 --- a/apps/xrp_app/xrp_pub_key.c +++ b/apps/xrp_app/xrp_pub_key.c @@ -61,7 +61,9 @@ *****************************************************************************/ #include "bip32.h" +#include "composable_app_queue.h" #include "curves.h" +#include "exchange_main.h" #include "hasher.h" #include "reconstruct_wallet_flow.h" #include "status_api.h" @@ -254,6 +256,14 @@ static bool validate_request(const xrp_get_public_keys_intiate_request_t *req, } } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, req->wallet_id, sizeof(req->wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; + + exchange_app_validate_caq(data); + return status; } diff --git a/apps/xrp_app/xrp_txn.c b/apps/xrp_app/xrp_txn.c index 7c09c845b..e1d4f1f09 100644 --- a/apps/xrp_app/xrp_txn.c +++ b/apps/xrp_app/xrp_txn.c @@ -63,6 +63,8 @@ #include +#include "composable_app_queue.h" +#include "exchange_main.h" #include "reconstruct_wallet_flow.h" #include "status_api.h" #include "ui_core_confirm.h" @@ -233,6 +235,16 @@ static bool validate_request_data(const xrp_sign_txn_request_t *request) { ERROR_DATA_FLOW_INVALID_DATA); status = false; } + + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_SEND; + + exchange_app_validate_caq(data); return status; } @@ -464,4 +476,4 @@ void xrp_sign_transaction(xrp_query_t *query) { } return; -} \ No newline at end of file +} From 7a51fbc108706eafc3493cd07b3ff8d22aab1a34 Mon Sep 17 00:00:00 2001 From: Tejasv Sharma Date: Fri, 18 Apr 2025 14:47:46 +0530 Subject: [PATCH 28/75] chore: Dummy commit --- apps/btc_family/btc_pub_key.c | 3 ++- apps/btc_family/btc_txn.c | 3 ++- apps/evm_family/evm_pub_key.c | 3 ++- apps/evm_family/evm_sign_txn.c | 3 ++- version.txt | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/btc_family/btc_pub_key.c b/apps/btc_family/btc_pub_key.c index e44cfb0bd..7e983e91d 100644 --- a/apps/btc_family/btc_pub_key.c +++ b/apps/btc_family/btc_pub_key.c @@ -64,6 +64,7 @@ #include "bip32.h" #include "btc_api.h" +#include "btc_app.h" #include "btc_helpers.h" #include "btc_priv.h" #include "coin_utils.h" @@ -178,7 +179,7 @@ static bool validate_request_data(btc_get_public_key_request_t *request) { status = false; } - caq_node_data_t data = {.applet_id = get_applet_id()}; + caq_node_data_t data = {.applet_id = get_btc_app_desc()->id}; memzero(data.params, sizeof(data.params)); memcpy(data.params, diff --git a/apps/btc_family/btc_txn.c b/apps/btc_family/btc_txn.c index 06380eb88..21e3214b0 100644 --- a/apps/btc_family/btc_txn.c +++ b/apps/btc_family/btc_txn.c @@ -66,6 +66,7 @@ #include "bip32.h" #include "btc_api.h" +#include "btc_app.h" #include "btc_helpers.h" #include "btc_inputs_validator.h" #include "btc_priv.h" @@ -308,7 +309,7 @@ static bool validate_request_data(const btc_sign_txn_request_t *request) { status = false; } - caq_node_data_t data = {.applet_id = get_applet_id()}; + caq_node_data_t data = {.applet_id = get_btc_app_desc()->id}; memzero(data.params, sizeof(data.params)); memcpy(data.params, diff --git a/apps/evm_family/evm_pub_key.c b/apps/evm_family/evm_pub_key.c index 134f564d5..434cd60f3 100644 --- a/apps/evm_family/evm_pub_key.c +++ b/apps/evm_family/evm_pub_key.c @@ -65,6 +65,7 @@ #include "address.h" #include "composable_app_queue.h" +#include "eth_app.h" #include "evm_api.h" #include "evm_helpers.h" #include "evm_priv.h" @@ -277,7 +278,7 @@ static bool validate_request_data(evm_get_public_keys_request_t *request, } } - caq_node_data_t data = {.applet_id = get_applet_id()}; + caq_node_data_t data = {.applet_id = get_eth_app_desc()->id}; memzero(data.params, sizeof(data.params)); memcpy(data.params, diff --git a/apps/evm_family/evm_sign_txn.c b/apps/evm_family/evm_sign_txn.c index c9b5a0014..743117a35 100644 --- a/apps/evm_family/evm_sign_txn.c +++ b/apps/evm_family/evm_sign_txn.c @@ -62,6 +62,7 @@ #include "address.h" #include "composable_app_queue.h" +#include "eth_app.h" #include "evm_api.h" #include "evm_helpers.h" #include "evm_priv.h" @@ -246,7 +247,7 @@ static bool validate_request_data(const evm_sign_txn_request_t *request) { status = false; } - caq_node_data_t data = {.applet_id = get_applet_id()}; + caq_node_data_t data = {.applet_id = get_eth_app_desc()->id}; memzero(data.params, sizeof(data.params)); memcpy(data.params, diff --git a/version.txt b/version.txt index d2b4a851e..6bf409f20 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:007:004 +firmware version=000:006:008:001 hardware version=000:001:000:000 magic number=45227A01 From fe8a8a80c83a14e2e83f0cf657e396cbf764573d Mon Sep 17 00:00:00 2001 From: Tejasv Sharma Date: Sat, 19 Apr 2025 07:38:45 +0530 Subject: [PATCH 29/75] chore: Add error logs --- apps/exchange_app/exchange_main.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index 93a984cd9..dc6ec8914 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -62,6 +62,7 @@ #include "exchange_main.h" +#include #include #include "board.h" @@ -166,20 +167,6 @@ bool exchange_app_validate_caq(caq_node_data_t data) { return false; } - /*{*/ - /* char hex_arr[500] = {0};*/ - /* byte_array_to_hex_string(*/ - /* data.params, sizeof(data.params), hex_arr, sizeof(hex_arr));*/ - /* core_scroll_page("params", hex_arr, NULL);*/ - /*}*/ - /**/ - /*{*/ - /* char hex_arr[500] = {0};*/ - /* byte_array_to_hex_string(*/ - /* caq_data.params, sizeof(caq_data.params), hex_arr, sizeof(hex_arr));*/ - /* core_scroll_page("params", hex_arr, NULL);*/ - /*}*/ - if (caq_data.applet_id == data.applet_id && memcmp(caq_data.params, data.params, sizeof(data.params)) == 0) { if (caq_data.applet_id != exchange_app_desc.id) { @@ -190,6 +177,22 @@ bool exchange_app_validate_caq(caq_node_data_t data) { return true; } + { + char hex_arr[500] = {0}; + char title[100] = {0}; + snprintf(title, 100, "%ld", data.applet_id); + byte_array_to_hex_string(data.params, 40, hex_arr, 100); + LOG_ERROR("CAQ Invalid data received: %ld [%s]", title, hex_arr); + } + + { + char hex_arr[500] = {0}; + char title[100] = {0}; + snprintf(title, 100, "%ld", caq_data.applet_id); + byte_array_to_hex_string(caq_data.params, 40, hex_arr, 100); + LOG_ERROR("CAQ data exptected: %ld [%s]", title, hex_arr); + } + delay_scr_init("Invalid operation during Swap\n rebooting...", DELAY_TIME); BSP_reset(); From db55478d17730a57604c34573123a0dbdb4f3073 Mon Sep 17 00:00:00 2001 From: Tejasv Sharma Date: Mon, 21 Apr 2025 07:01:23 +0530 Subject: [PATCH 30/75] feat: Use signature verification in send flow --- apps/btc_family/btc_txn.c | 12 +++- apps/evm_family/evm_sign_txn.c | 2 +- apps/evm_family/evm_txn_helpers.h | 3 + apps/evm_family/evm_user_verification.c | 8 +++ apps/exchange_app/exchange_get_signature.c | 18 +++--- apps/exchange_app/exchange_main.c | 58 ++++++++++++++++++- apps/exchange_app/exchange_main.h | 2 + apps/exchange_app/exchange_store_signature.c | 9 ++- apps/icp_app/icp_txn.c | 9 ++- apps/solana_app/solana_sign_txn.c | 9 ++- apps/starknet_app/starknet_sign_txn.c | 10 +++- apps/tron_app/tron_context.h | 3 +- apps/tron_app/tron_parse_contracts.c | 15 ++++- apps/tron_app/tron_sign_txn.c | 7 ++- apps/xrp_app/xrp_txn.c | 9 ++- .../exchange/store_signature.options | 2 +- 16 files changed, 149 insertions(+), 27 deletions(-) diff --git a/apps/btc_family/btc_txn.c b/apps/btc_family/btc_txn.c index 21e3214b0..b5422a84d 100644 --- a/apps/btc_family/btc_txn.c +++ b/apps/btc_family/btc_txn.c @@ -277,7 +277,7 @@ static bool send_script_sig(btc_query_t *query, const scrip_sig_t *sigs); /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ - +static bool use_signature_verification = false; static btc_txn_context_t *btc_txn_context = NULL; /***************************************************************************** @@ -317,7 +317,7 @@ static bool validate_request_data(const btc_sign_txn_request_t *request) { sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_SEND; - exchange_app_validate_caq(data); + use_signature_verification = exchange_app_validate_caq(data); return status; } @@ -586,6 +586,14 @@ static bool get_user_verification() { btc_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, status); return false; } + + if (use_signature_verification) { + if (!exchange_validate_stored_signature(address, sizeof(address))) { + btc_send_error(ERROR_COMMON_ERROR_UNKNOWN_ERROR_TAG, status); + return false; + } + } + if (!core_scroll_page(title, address, btc_send_error) || !core_scroll_page(title, value, btc_send_error)) { return false; diff --git a/apps/evm_family/evm_sign_txn.c b/apps/evm_family/evm_sign_txn.c index 743117a35..65dad9b83 100644 --- a/apps/evm_family/evm_sign_txn.c +++ b/apps/evm_family/evm_sign_txn.c @@ -255,7 +255,7 @@ static bool validate_request_data(const evm_sign_txn_request_t *request) { sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_SEND; - exchange_app_validate_caq(data); + txn_context->use_signature_verification = exchange_app_validate_caq(data); return status; } diff --git a/apps/evm_family/evm_txn_helpers.h b/apps/evm_family/evm_txn_helpers.h index 4ca5f457c..11f17c827 100644 --- a/apps/evm_family/evm_txn_helpers.h +++ b/apps/evm_family/evm_txn_helpers.h @@ -108,6 +108,9 @@ typedef struct { /// pointer to maintain a list of display nodes ui_display_node *display_node; + + /// for exchange app + bool use_signature_verification; } evm_txn_context_t; /***************************************************************************** diff --git a/apps/evm_family/evm_user_verification.c b/apps/evm_family/evm_user_verification.c index fedbc1cfc..7a0e4b1cf 100644 --- a/apps/evm_family/evm_user_verification.c +++ b/apps/evm_family/evm_user_verification.c @@ -66,6 +66,7 @@ #include "constant_texts.h" #include "evm_api.h" #include "evm_priv.h" +#include "exchange_main.h" #include "ui_core_confirm.h" #include "ui_screens.h" @@ -124,6 +125,13 @@ bool evm_verify_transfer(const evm_txn_context_t *txn_context) { to_address, &address[2], false, g_evm_app->chain_id); snprintf( display, sizeof(display), UI_TEXT_SEND_PROMPT, unit, g_evm_app->name); + + if (txn_context->use_signature_verification) { + if (!exchange_validate_stored_signature(address, sizeof(address))) { + return status; + } + } + if (!core_scroll_page(NULL, display, evm_send_error) || !core_scroll_page(ui_text_verify_address, address, evm_send_error)) { return status; diff --git a/apps/exchange_app/exchange_get_signature.c b/apps/exchange_app/exchange_get_signature.c index 60baa3003..06b77d279 100644 --- a/apps/exchange_app/exchange_get_signature.c +++ b/apps/exchange_app/exchange_get_signature.c @@ -60,6 +60,8 @@ * INCLUDES *****************************************************************************/ +#include "core_session.h" +#include "core_shared_context.h" #include "exchange/get_signature.pb.h" #include "exchange_api.h" #include "exchange_main.h" @@ -97,8 +99,6 @@ static bool check_which_request(const exchange_query_t *query, pb_size_t which_request); -static bool send_signature(exchange_query_t *query, exchange_result_t *result); - /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ @@ -129,11 +129,6 @@ static bool check_which_request(const exchange_query_t *query, return true; } -static bool send_signature(exchange_query_t *query, exchange_result_t *result) { - exchange_send_result(result); - return true; -} - /***************************************************************************** * GLOBAL FUNCTIONS *****************************************************************************/ @@ -149,7 +144,10 @@ void exchange_get_signature(exchange_query_t *query) { result.get_signature.which_response = EXCHANGE_GET_SIGNATURE_RESPONSE_RESULT_TAG; - if (send_signature(query, &result) == false) { - // TODO: handle signature export failed - } + memcpy(result.get_signature.result.signature, + shared_context, + sizeof(result.get_signature.result.signature)); + result.get_signature.result.index = SESSION_KEY_INDEX; + + exchange_send_result(&result); } diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index dc6ec8914..a023e2f4e 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -65,11 +65,17 @@ #include #include +#include "base58.h" +#include "bip32.h" #include "board.h" #include "composable_app_queue.h" +#include "core_session.h" +#include "core_shared_context.h" +#include "curves.h" #include "exchange/core.pb.h" #include "exchange_api.h" #include "exchange_priv.h" +#include "nist256p1.h" #include "status_api.h" #include "ui_core_confirm.h" #include "ui_delay.h" @@ -120,6 +126,23 @@ static const cy_app_desc_t exchange_app_desc = {.id = 24, /***************************************************************************** * STATIC FUNCTIONS *****************************************************************************/ +static void derive_server_public_key(uint8_t *server_verification_pub_key) { + HDNode node; + char xpub[XPUB_SIZE] = {'\0'}; + + base58_encode_check(get_card_root_xpub(), + FS_KEYSTORE_XPUB_LEN, + nist256p1_info.hasher_base58, + xpub, + XPUB_SIZE); + + hdnode_deserialize_public( + (char *)xpub, 0x0488b21e, NIST256P1_NAME, &node, NULL); + hdnode_public_ckd(&node, SESSION_KEY_INDEX); + + memcpy(server_verification_pub_key, node.public_key, SESSION_PUB_KEY_SIZE); +} + void exchange_main(usb_event_t usb_evt, const void *app_config) { exchange_query_t query = EXCHANGE_QUERY_INIT_DEFAULT; @@ -172,6 +195,13 @@ bool exchange_app_validate_caq(caq_node_data_t data) { if (caq_data.applet_id != exchange_app_desc.id) { delay_scr_init("Swap", DELAY_SHORT); } + { + char hex_arr[500] = {0}; + char title[100] = {0}; + snprintf(title, 100, "%ld", data.applet_id); + byte_array_to_hex_string(data.params, 40, hex_arr, 100); + LOG_ERROR("Match %s [%s]", title, hex_arr); + } caq_pop(); return true; @@ -182,7 +212,7 @@ bool exchange_app_validate_caq(caq_node_data_t data) { char title[100] = {0}; snprintf(title, 100, "%ld", data.applet_id); byte_array_to_hex_string(data.params, 40, hex_arr, 100); - LOG_ERROR("CAQ Invalid data received: %ld [%s]", title, hex_arr); + LOG_ERROR("CAQ Invalid data received: %s [%s]", title, hex_arr); } { @@ -190,7 +220,7 @@ bool exchange_app_validate_caq(caq_node_data_t data) { char title[100] = {0}; snprintf(title, 100, "%ld", caq_data.applet_id); byte_array_to_hex_string(caq_data.params, 40, hex_arr, 100); - LOG_ERROR("CAQ data exptected: %ld [%s]", title, hex_arr); + LOG_ERROR("CAQ data exptected: %s [%s]", title, hex_arr); } delay_scr_init("Invalid operation during Swap\n rebooting...", DELAY_TIME); @@ -198,3 +228,27 @@ bool exchange_app_validate_caq(caq_node_data_t data) { return false; } + +bool exchange_validate_stored_signature(char *receiver, + size_t receiver_max_size) { + uint8_t sig[64] = {0}; + memcpy(sig, shared_context, sizeof(sig)); + + core_clear_shared_context(); + + uint8_t server_verification_pub_key[SESSION_PUB_KEY_SIZE]; + derive_server_public_key(server_verification_pub_key); + + size_t len = strnlen(receiver, receiver_max_size); + uint8_t hash[SHA256_DIGEST_LENGTH] = {0}; + + sha256_Raw((uint8_t *)receiver, len, hash); + + if (ecdsa_verify_digest(&nist256p1, server_verification_pub_key, sig, hash) != + 0) { + delay_scr_init("Failed to validate signature\n Do not proceed with Swap", + DELAY_TIME); + return false; + } + return true; +} diff --git a/apps/exchange_app/exchange_main.h b/apps/exchange_app/exchange_main.h index af88e653e..6ba61e390 100644 --- a/apps/exchange_app/exchange_main.h +++ b/apps/exchange_app/exchange_main.h @@ -50,4 +50,6 @@ typedef enum EXCHANGE_FLOW_TAGS { const cy_app_desc_t *get_exchange_app_desc(); bool exchange_app_validate_caq(caq_node_data_t data); +bool exchange_validate_stored_signature(char *receiver, + size_t receiver_max_size); #endif /* EXCHANGE_MAIN_H */ diff --git a/apps/exchange_app/exchange_store_signature.c b/apps/exchange_app/exchange_store_signature.c index 6793293e2..517f40598 100644 --- a/apps/exchange_app/exchange_store_signature.c +++ b/apps/exchange_app/exchange_store_signature.c @@ -60,7 +60,10 @@ * INCLUDES *****************************************************************************/ +#include + #include "composable_app_queue.h" +#include "core_shared_context.h" #include "exchange/store_signature.pb.h" #include "exchange_api.h" #include "exchange_main.h" @@ -140,7 +143,11 @@ void exchange_store_signature(exchange_query_t *query) { return; } - // TODO: do things here + core_clear_shared_context(); + + memcpy(shared_context, + query->store_signature.initiate.signature, + sizeof(query->store_signature.initiate.signature)); result.store_signature.which_response = EXCHANGE_STORE_SIGNATURE_RESPONSE_RESULT_TAG; diff --git a/apps/icp_app/icp_txn.c b/apps/icp_app/icp_txn.c index d22354be4..789ec487e 100644 --- a/apps/icp_app/icp_txn.c +++ b/apps/icp_app/icp_txn.c @@ -235,6 +235,7 @@ static bool send_signature(icp_query_t *query, const sig_t *signature); * STATIC VARIABLES *****************************************************************************/ static icp_txn_context_t *icp_txn_context = NULL; +static bool use_signature_verification = false; /***************************************************************************** * GLOBAL VARIABLES @@ -279,7 +280,7 @@ static bool validate_request_data(const icp_sign_txn_request_t *request) { sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_SEND; - exchange_app_validate_caq(data); + use_signature_verification = exchange_app_validate_caq(data); return status; } @@ -539,6 +540,12 @@ static bool get_user_verification_for_coin_txn(void) { to_address, ICP_ACCOUNT_ID_LENGTH * 2 + 1); + if (use_signature_verification) { + if (!exchange_validate_stored_signature(to_address, sizeof(to_address))) { + return false; + } + } + if (!core_scroll_page(ui_text_verify_address, to_address, icp_send_error)) { return false; } diff --git a/apps/solana_app/solana_sign_txn.c b/apps/solana_app/solana_sign_txn.c index 0e67af8fe..3c34e762c 100644 --- a/apps/solana_app/solana_sign_txn.c +++ b/apps/solana_app/solana_sign_txn.c @@ -218,6 +218,7 @@ static bool send_signature(solana_query_t *query, *****************************************************************************/ STATIC solana_txn_context_t *solana_txn_context = NULL; +static bool use_signature_verification = false; /***************************************************************************** * GLOBAL VARIABLES @@ -256,7 +257,7 @@ static bool validate_request_data(const solana_sign_txn_request_t *request) { sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_SEND; - exchange_app_validate_caq(data); + use_signature_verification = exchange_app_validate_caq(data); return status; } @@ -436,6 +437,12 @@ static bool verify_solana_transfer_sol_transaction() { return false; } + if (use_signature_verification) { + if (!exchange_validate_stored_signature(address, sizeof(address))) { + return false; + } + } + if (!core_scroll_page(ui_text_verify_address, address, solana_send_error)) { return false; } diff --git a/apps/starknet_app/starknet_sign_txn.c b/apps/starknet_app/starknet_sign_txn.c index 7a708b95a..28b0a16a2 100644 --- a/apps/starknet_app/starknet_sign_txn.c +++ b/apps/starknet_app/starknet_sign_txn.c @@ -222,6 +222,8 @@ static void stark_amount_get_decimal_str(const uint8_t *byte_array, *****************************************************************************/ static starknet_txn_context_t *starknet_txn_context = NULL; +static bool use_signature_verification = false; + /***************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ @@ -265,7 +267,7 @@ static bool validate_request_data(const starknet_sign_txn_request_t *request) { sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_SEND; - exchange_app_validate_caq(data); + use_signature_verification = exchange_app_validate_caq(data); return status; } @@ -421,6 +423,12 @@ static bool get_invoke_txn_user_verification() { &address[2], sizeof(address)); + if (use_signature_verification) { + if (!exchange_validate_stored_signature(address, sizeof(address))) { + return false; + } + } + if (!core_scroll_page(ui_text_verify_address, address, starknet_send_error)) { return false; } diff --git a/apps/tron_app/tron_context.h b/apps/tron_app/tron_context.h index 539bd75e2..75347eb4d 100644 --- a/apps/tron_app/tron_context.h +++ b/apps/tron_app/tron_context.h @@ -41,6 +41,7 @@ typedef struct { * @param[in] raw_txn: tron raw transaction * @return bool True if decoding was successful, else false */ -bool extract_contract_info(tron_transaction_raw_t *raw_txn); +bool extract_contract_info(tron_transaction_raw_t *raw_txn, + bool use_signature_verification); #endif /* TRON_CONTEXT_H */ diff --git a/apps/tron_app/tron_parse_contracts.c b/apps/tron_app/tron_parse_contracts.c index bea49e59b..4efe25668 100644 --- a/apps/tron_app/tron_parse_contracts.c +++ b/apps/tron_app/tron_parse_contracts.c @@ -72,6 +72,7 @@ #include "coin_utils.h" #include "curves.h" #include "ecdsa.h" +#include "exchange_main.h" #include "hasher.h" #include "secp256k1.h" #include "sha2.h" @@ -283,7 +284,8 @@ static bool parse_unverified(uint8_t *data, uint8_t *contract_address) { return true; } -static bool transfer_contract_txn(tron_transaction_contract_t *contract) { +static bool transfer_contract_txn(tron_transaction_contract_t *contract, + bool use_signature_verification) { uint8_t to_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; // uint8_t owner_address[TRON_INITIAL_ADDRESS_LENGTH] = {0}; int64_t amount = 0; @@ -314,6 +316,12 @@ static bool transfer_contract_txn(tron_transaction_contract_t *contract) { return false; } + if (use_signature_verification) { + if (!exchange_validate_stored_signature(address, sizeof(address))) { + return false; + } + } + if (!core_scroll_page(ui_text_verify_address, address, tron_send_error)) { return false; } @@ -430,7 +438,8 @@ static bool transfer_asset_contract_txn(tron_transaction_contract_t *contract) { * GLOBAL FUNCTIONS *****************************************************************************/ -bool extract_contract_info(tron_transaction_raw_t *raw_txn) { +bool extract_contract_info(tron_transaction_raw_t *raw_txn, + bool use_signature_verification) { if (!(raw_txn->contract_count > 0)) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, ERROR_DATA_FLOW_INVALID_DATA); @@ -442,7 +451,7 @@ bool extract_contract_info(tron_transaction_raw_t *raw_txn) { switch (contract.type) { case TRON_TRANSACTION_CONTRACT_TRANSFER_CONTRACT: { // Transfer TRX type - if (!transfer_contract_txn(&contract)) { + if (!transfer_contract_txn(&contract, use_signature_verification)) { return false; } break; diff --git a/apps/tron_app/tron_sign_txn.c b/apps/tron_app/tron_sign_txn.c index a8409cf28..12ea5a18f 100644 --- a/apps/tron_app/tron_sign_txn.c +++ b/apps/tron_app/tron_sign_txn.c @@ -223,6 +223,8 @@ static bool send_signature(tron_query_t *query, STATIC tron_txn_context_t *tron_txn_context = NULL; +static bool use_signature_verification = false; + /***************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ @@ -260,7 +262,7 @@ static bool validate_request_data(const tron_sign_txn_request_t *request) { sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_SEND; - exchange_app_validate_caq(data); + use_signature_verification = exchange_app_validate_caq(data); return status; } @@ -360,7 +362,8 @@ STATIC bool tron_fetch_valid_transaction(tron_query_t *query) { STATIC bool tron_get_user_verification() { // extract raw - if (!extract_contract_info(tron_txn_context->raw_txn)) { + if (!extract_contract_info(tron_txn_context->raw_txn, + use_signature_verification)) { tron_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, ERROR_DATA_FLOW_DECODING_FAILED); return false; diff --git a/apps/xrp_app/xrp_txn.c b/apps/xrp_app/xrp_txn.c index e1d4f1f09..26e963539 100644 --- a/apps/xrp_app/xrp_txn.c +++ b/apps/xrp_app/xrp_txn.c @@ -201,6 +201,7 @@ static bool send_signature(xrp_query_t *query, const der_sig_t *der_signature); * STATIC VARIABLES *****************************************************************************/ static xrp_txn_context_t *xrp_txn_context = NULL; +static bool use_signature_verification = false; /***************************************************************************** * GLOBAL VARIABLES @@ -244,7 +245,7 @@ static bool validate_request_data(const xrp_sign_txn_request_t *request) { sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_SEND; - exchange_app_validate_caq(data); + use_signature_verification = exchange_app_validate_caq(data); return status; } @@ -359,6 +360,12 @@ static bool get_user_verification(void) { return false; } + if (use_signature_verification) { + if (!exchange_validate_stored_signature(to_address, sizeof(to_address))) { + return false; + } + } + if (!core_scroll_page(ui_text_verify_address, to_address, xrp_send_error)) { return false; } diff --git a/common/proto-options/exchange/store_signature.options b/common/proto-options/exchange/store_signature.options index 353b0902a..2b3f5449d 100644 --- a/common/proto-options/exchange/store_signature.options +++ b/common/proto-options/exchange/store_signature.options @@ -1 +1 @@ -exchange.StoreSignatureIntiateRequest.signature type:FT_STATIC max_size:32 fixed_length:true +exchange.StoreSignatureIntiateRequest.signature type:FT_STATIC max_size:64 fixed_length:true From 774eeea020ae0cc3208b755113a29e1dbdeb9010 Mon Sep 17 00:00:00 2001 From: Tejasv Sharma Date: Mon, 21 Apr 2025 09:43:03 +0530 Subject: [PATCH 31/75] feat: Sign address in receive flow for exchange app --- apps/btc_family/btc_pub_key.c | 8 ++++++- apps/evm_family/evm_pub_key.c | 8 ++++++- apps/exchange_app/exchange_main.c | 21 +++++++++++++++++++ apps/exchange_app/exchange_main.h | 1 + apps/icp_app/icp_pub_key.c | 7 ++++++- apps/near_app/near_pub_key.c | 8 ++++++- apps/solana_app/solana_pub_key.c | 7 ++++++- apps/starknet_app/starknet_pub_key.c | 7 ++++++- apps/tron_app/tron_pub_key.c | 8 +++++-- apps/xrp_app/xrp_pub_key.c | 7 ++++++- .../exchange/get_signature.options | 2 +- 11 files changed, 74 insertions(+), 10 deletions(-) diff --git a/apps/btc_family/btc_pub_key.c b/apps/btc_family/btc_pub_key.c index 7e983e91d..f3ff53489 100644 --- a/apps/btc_family/btc_pub_key.c +++ b/apps/btc_family/btc_pub_key.c @@ -157,6 +157,7 @@ static void send_public_key(const uint8_t *public_key); /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ +static bool sign_address = false; static bool check_which_request(const btc_query_t *query, pb_size_t which_request) { @@ -187,7 +188,7 @@ static bool validate_request_data(btc_get_public_key_request_t *request) { sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; - exchange_app_validate_caq(data); + sign_address = exchange_app_validate_caq(data); return status; } @@ -299,6 +300,11 @@ void btc_get_pub_key(btc_query_t *query) { delay_scr_init(ui_text_processing, DELAY_SHORT); size_t length = btc_get_address(seed, path, path_length, public_key, msg); memzero(seed, sizeof(seed)); + + if (sign_address) { + exchange_sign_address(msg, sizeof(msg)); + } + if (0 < length && true == core_scroll_page(ui_text_receive_on, msg, btc_send_error)) { set_app_flow_status(BTC_GET_PUBLIC_KEY_STATUS_VERIFY); diff --git a/apps/evm_family/evm_pub_key.c b/apps/evm_family/evm_pub_key.c index 434cd60f3..4cbe59063 100644 --- a/apps/evm_family/evm_pub_key.c +++ b/apps/evm_family/evm_pub_key.c @@ -227,6 +227,8 @@ static bool get_address(const evm_address_format_t format, * STATIC VARIABLES *****************************************************************************/ +static bool sign_address = false; + /***************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ @@ -286,7 +288,7 @@ static bool validate_request_data(evm_get_public_keys_request_t *request, sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; - exchange_app_validate_caq(data); + sign_address = exchange_app_validate_caq(data); return status; } @@ -496,6 +498,10 @@ void evm_get_pub_keys(evm_query_t *query) { return; } + if (sign_address) { + exchange_sign_address(address, sizeof(address)); + } + if (!core_scroll_page(ui_text_receive_on, address, evm_send_error)) { return; } diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index a023e2f4e..386d040f5 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -62,9 +62,11 @@ #include "exchange_main.h" +#include #include #include +#include "atecc_utils.h" #include "base58.h" #include "bip32.h" #include "board.h" @@ -76,6 +78,7 @@ #include "exchange_api.h" #include "exchange_priv.h" #include "nist256p1.h" +#include "sha2.h" #include "status_api.h" #include "ui_core_confirm.h" #include "ui_delay.h" @@ -252,3 +255,21 @@ bool exchange_validate_stored_signature(char *receiver, } return true; } + +void exchange_sign_address(char *address, size_t address_max_size) { + uint8_t hash[SHA256_DIGEST_LENGTH] = {0}; + size_t len = strnlen(address, address_max_size); + sha256_Raw((uint8_t *)address, len, hash); + + auth_data_t data = atecc_sign(hash); + core_clear_shared_context(); + size_t offset = 0; + memcpy(shared_context, data.signature, sizeof(data.signature)); + offset += sizeof(data.signature); + + memcpy(shared_context + offset, data.postfix1, sizeof(data.postfix1)); + offset += sizeof(data.postfix1); + + memcpy(shared_context + offset, data.postfix2, sizeof(data.postfix2)); + offset += sizeof(data.postfix2); +} diff --git a/apps/exchange_app/exchange_main.h b/apps/exchange_app/exchange_main.h index 6ba61e390..31c4b02df 100644 --- a/apps/exchange_app/exchange_main.h +++ b/apps/exchange_app/exchange_main.h @@ -52,4 +52,5 @@ const cy_app_desc_t *get_exchange_app_desc(); bool exchange_app_validate_caq(caq_node_data_t data); bool exchange_validate_stored_signature(char *receiver, size_t receiver_max_size); +void exchange_sign_address(char *address, size_t address_max_size); #endif /* EXCHANGE_MAIN_H */ diff --git a/apps/icp_app/icp_pub_key.c b/apps/icp_app/icp_pub_key.c index 197429560..d8c91643a 100644 --- a/apps/icp_app/icp_pub_key.c +++ b/apps/icp_app/icp_pub_key.c @@ -219,6 +219,7 @@ static bool get_user_consent(const pb_size_t which_request, /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ +static bool sign_address = false; static bool check_which_request(const icp_query_t *query, pb_size_t which_request) { @@ -270,7 +271,7 @@ static bool validate_request(const icp_get_public_keys_intiate_request_t *req, memcpy(data.params, req->wallet_id, sizeof(req->wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; - exchange_app_validate_caq(data); + sign_address = exchange_app_validate_caq(data); return status; } @@ -550,6 +551,10 @@ void icp_get_pub_keys(icp_query_t *query) { char account_id[200] = {0}; get_account_id_to_display(principal, account_id, sizeof(account_id)); + // NOTE: not sure if this is enough or we need to sign principal id instead + if (sign_address) { + exchange_sign_address(account_id, sizeof(account_id)); + } if (!core_scroll_page(ui_text_account_id, account_id, icp_send_error)) { return; } diff --git a/apps/near_app/near_pub_key.c b/apps/near_app/near_pub_key.c index 953427bad..01e9449a8 100644 --- a/apps/near_app/near_pub_key.c +++ b/apps/near_app/near_pub_key.c @@ -209,6 +209,7 @@ static bool get_user_consent(const pb_size_t which_request, /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ +static bool sign_address = false; static bool check_which_request(const near_query_t *query, pb_size_t which_request) { @@ -260,7 +261,7 @@ static bool validate_request(const near_get_public_keys_intiate_request_t *req, memcpy(data.params, req->wallet_id, sizeof(req->wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; - exchange_app_validate_caq(data); + sign_address = exchange_app_validate_caq(data); return status; } @@ -432,6 +433,11 @@ void near_get_pub_keys(near_query_t *query) { char address[100] = ""; byte_array_to_hex_string( pubkey_list[0], sizeof(pubkey_list[0]), address, sizeof(address)); + + if (sign_address) { + exchange_sign_address(address, sizeof(address)); + } + if (!core_scroll_page(ui_text_receive_on, address, near_send_error)) { return; } diff --git a/apps/solana_app/solana_pub_key.c b/apps/solana_app/solana_pub_key.c index 970545f91..0c0eb28ee 100644 --- a/apps/solana_app/solana_pub_key.c +++ b/apps/solana_app/solana_pub_key.c @@ -206,6 +206,7 @@ static bool get_user_consent(const pb_size_t which_request, /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ +static bool sign_address = false; /***************************************************************************** * GLOBAL VARIABLES @@ -266,7 +267,7 @@ STATIC bool validate_request_data(solana_get_public_keys_request_t *request, sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; - exchange_app_validate_caq(data); + sign_address = exchange_app_validate_caq(data); return status; } @@ -447,6 +448,10 @@ void solana_get_pub_keys(solana_query_t *query) { return; }; + if (sign_address) { + exchange_sign_address(address, sizeof(address)); + } + if (!core_scroll_page(ui_text_receive_on, address, solana_send_error)) { return; } diff --git a/apps/starknet_app/starknet_pub_key.c b/apps/starknet_app/starknet_pub_key.c index 131a7df89..c9a0c47c0 100644 --- a/apps/starknet_app/starknet_pub_key.c +++ b/apps/starknet_app/starknet_pub_key.c @@ -229,6 +229,7 @@ static void starknet_derive_argent_address(const uint8_t *pub_key, char *addr); /***************************************************************************** * static VARIABLES *****************************************************************************/ +static bool sign_address = false; /***************************************************************************** * GLOBAL VARIABLES @@ -289,7 +290,7 @@ static bool validate_request_data(starknet_get_public_keys_request_t *request, sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; - exchange_app_validate_caq(data); + sign_address = exchange_app_validate_caq(data); return status; } @@ -545,6 +546,10 @@ void starknet_get_pub_keys(starknet_query_t *query) { snprintf(address + index, sizeof(address) - index, raw_address); } + if (sign_address) { + exchange_sign_address(address, sizeof(address)); + } + if (!core_scroll_page(ui_text_receive_on, address, starknet_send_error)) { return; } diff --git a/apps/tron_app/tron_pub_key.c b/apps/tron_app/tron_pub_key.c index 396316410..dee9e30c9 100644 --- a/apps/tron_app/tron_pub_key.c +++ b/apps/tron_app/tron_pub_key.c @@ -213,7 +213,7 @@ static bool get_user_consent(const pb_size_t which_request, /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ - +static bool sign_address = false; /***************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ @@ -274,7 +274,7 @@ static bool validate_request_data(tron_get_public_keys_request_t *request, sizeof(request->initiate.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; - exchange_app_validate_caq(data); + sign_address = exchange_app_validate_caq(data); return status; } @@ -470,6 +470,10 @@ void tron_get_pub_keys(tron_query_t *query) { return; } + if (sign_address) { + exchange_sign_address(main_address, sizeof(main_address)); + } + if (!core_scroll_page(ui_text_receive_on, main_address, tron_send_error)) { return; } diff --git a/apps/xrp_app/xrp_pub_key.c b/apps/xrp_app/xrp_pub_key.c index 99555b39a..d44d54e8d 100644 --- a/apps/xrp_app/xrp_pub_key.c +++ b/apps/xrp_app/xrp_pub_key.c @@ -211,6 +211,7 @@ static bool get_user_consent(const pb_size_t which_request, /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ +static bool sign_address = false; static bool check_which_request(const xrp_query_t *query, pb_size_t which_request) { @@ -262,7 +263,7 @@ static bool validate_request(const xrp_get_public_keys_intiate_request_t *req, memcpy(data.params, req->wallet_id, sizeof(req->wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; - exchange_app_validate_caq(data); + sign_address = exchange_app_validate_caq(data); return status; } @@ -456,6 +457,10 @@ void xrp_get_pub_keys(xrp_query_t *query) { return; } + if (sign_address) { + exchange_sign_address(address, sizeof(address)); + } + if (!core_scroll_page(ui_text_receive_on, address, xrp_send_error)) { return; } diff --git a/common/proto-options/exchange/get_signature.options b/common/proto-options/exchange/get_signature.options index d737329fb..68c5fa92d 100644 --- a/common/proto-options/exchange/get_signature.options +++ b/common/proto-options/exchange/get_signature.options @@ -1 +1 @@ -exchange.GetSignatureResultResponse.signature type:FT_STATIC max_size:32 fixed_length:true +exchange.GetSignatureResultResponse.signature type:FT_STATIC max_size:94 fixed_length:true From db42c79fef6143f523888689367f23043f438b15 Mon Sep 17 00:00:00 2001 From: Tejasv Sharma Date: Mon, 21 Apr 2025 10:05:09 +0530 Subject: [PATCH 32/75] chore: Add doxygen comments --- apps/exchange_app/exchange_main.h | 36 +++++++++++++++++++++ apps/exchange_app/exchange_priv.h | 28 ++++++++++++++++ common/core/composable_app_queue.h | 52 +++++++++++++++++++++++++++--- 3 files changed, 111 insertions(+), 5 deletions(-) diff --git a/apps/exchange_app/exchange_main.h b/apps/exchange_app/exchange_main.h index 31c4b02df..5d3b278e8 100644 --- a/apps/exchange_app/exchange_main.h +++ b/apps/exchange_app/exchange_main.h @@ -49,8 +49,44 @@ typedef enum EXCHANGE_FLOW_TAGS { */ const cy_app_desc_t *get_exchange_app_desc(); +/** + * @brief Validates the data against the data at the front of the composable app + * queue. + * + * It compares the provided data with the data at the front of the queue. If + * they match, it removes the data from the queue. If they do not match, it + * triggers a reset. Does nothing if no data is present. + * + * @param data The data to validate against the queue. + * @return true If the validation is successful and data is popped. + * @return false If the validation fails. + */ bool exchange_app_validate_caq(caq_node_data_t data); + +/** + * @brief Validates a stored signature against a server public key. + * + * Derives the server's public key and verifies the signature against the + * provided receiver address. + * + * @param receiver Pointer to the receiver address string. + * @param receiver_max_size Maximum size of the receiver buffer. + * @return true If the signature is valid. + * @return false If the signature is invalid. + */ bool exchange_validate_stored_signature(char *receiver, size_t receiver_max_size); + +/** + * @brief Signs an address using the ATECC608A and stores the signature in the + * shared context. + * + * This function calculates the SHA256 hash of the address, signs it using the + * ATECC608A, and stores the resulting signature and postfix data in the shared + * context. + * + * @param address Pointer to the address string to be signed. + * @param address_max_size Maximum size of the address buffer. + */ void exchange_sign_address(char *address, size_t address_max_size); #endif /* EXCHANGE_MAIN_H */ diff --git a/apps/exchange_app/exchange_priv.h b/apps/exchange_app/exchange_priv.h index a6f800474..da3f5f306 100644 --- a/apps/exchange_app/exchange_priv.h +++ b/apps/exchange_app/exchange_priv.h @@ -38,10 +38,38 @@ * GLOBAL FUNCTION PROTOTYPES *****************************************************************************/ +/** + * @brief Initiates the exchange flow by pushing data onto the composable app + * queue. + * + * This function clears the existing queue, then pushes data for the receive + * flow, fetching the signature, storing the signature, and finally the send + * flow. + * + * @param query Pointer to the exchange query structure. + */ void exchange_initiate_flow(exchange_query_t *query); +/** + * @brief Retrieves the signature from the shared context and sends it as a + * result. + * + * This function retrieves the signature stored in the shared context, copies it + * into the result structure, and sends the result. + * + * @param query Pointer to the exchange query structure. + */ void exchange_get_signature(exchange_query_t *query); +/** + * @brief Stores the provided signature in the shared context. + * + * This function clears the existing shared context and copies the provided + * signature into it. + * + * @param query Pointer to the exchange query structure containing the signature + * to store. + */ void exchange_store_signature(exchange_query_t *query); #endif diff --git a/common/core/composable_app_queue.h b/common/core/composable_app_queue.h index 072d05cc2..0f30e4520 100644 --- a/common/core/composable_app_queue.h +++ b/common/core/composable_app_queue.h @@ -34,16 +34,58 @@ typedef struct composable_app_queue { int count; } composable_app_queue_t; -bool caq_is_empty(); +/** + * @brief Initializes the composable app queue. + * + * This function creates and initializes the composable app queue. It must be + * called before any other queue operations. + */ +void caq_init(void); +/** + * @brief Checks if the composable app queue is empty. + * + * @return true If the queue is empty. + * @return false If the queue is not empty. + */ +bool caq_is_empty(void); + +/** + * @brief Pushes data onto the composable app queue. + * + * @param data The data to be pushed onto the queue. + */ void caq_push(caq_node_data_t data); -bool caq_pop(); +/** + * @brief Pops data from the composable app queue. + * + * @return true If data was successfully popped from the queue. + * @return false If the queue was empty. + */ +bool caq_pop(void); +/** + * @brief Peeks at the data at the front of the composable app queue. + * + * @param status Pointer to a boolean variable to indicate if the peek was + * successful. + * Will be set to true if successful, false otherwise. + * + * @return caq_node_data_t The data at the front of the queue. If the queue is + * empty, + * it returns a zeroed out data. Check the status + * parameter + * to see if the queue was empty. + */ caq_node_data_t caq_peek(bool *status); -bool caq_clear(); - -void caq_init(); +/** + * @brief Clears all elements from the composable app queue. + * + * @return true If the queue was successfully cleared. + * @return false If there was an error during clearing. + */ +bool caq_clear(void); #endif // COMPOSABLE_APP_QUEUE From 182354aafc24c5eeb8091ec8806a601b1d555e86 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 16 Apr 2025 16:57:22 +0530 Subject: [PATCH 33/75] fix: Correct icp txn verification texts --- apps/icp_app/icp_txn.c | 28 +++++++++++++--------------- src/constant_texts.c | 3 ++- src/constant_texts.h | 2 ++ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/apps/icp_app/icp_txn.c b/apps/icp_app/icp_txn.c index 789ec487e..84a26b8f6 100644 --- a/apps/icp_app/icp_txn.c +++ b/apps/icp_app/icp_txn.c @@ -497,13 +497,10 @@ static bool get_user_verification_for_token_txn(void) { return false; } - snprintf(display_fee, - sizeof(display_fee), - UI_TEXT_SEND_TXN_FEE, - fee_decimal_string, - token.symbol); - - if (!core_scroll_page(UI_TEXT_TXN_FEE, display_fee, icp_send_error)) { + snprintf( + display_fee, sizeof(display_fee), UI_TEXT_VERIFY_FEE, fee_decimal_string, token.symbol); + + if (!core_confirmation(display_fee, icp_send_error)) { return false; } } @@ -533,20 +530,20 @@ static bool get_user_verification_for_coin_txn(void) { const icp_coin_transfer_t *decoded_utxn = icp_txn_context->raw_icp_coin_transfer_txn; - char to_address[ICP_ACCOUNT_ID_LENGTH * 2 + 1] = ""; + char to_account_id[ICP_ACCOUNT_ID_LENGTH * 2 + 1] = ""; byte_array_to_hex_string(decoded_utxn->to, ICP_ACCOUNT_ID_LENGTH, - to_address, + to_account_id, ICP_ACCOUNT_ID_LENGTH * 2 + 1); if (use_signature_verification) { - if (!exchange_validate_stored_signature(to_address, sizeof(to_address))) { + if (!exchange_validate_stored_signature(to_account_id, sizeof(to_account_id))) { return false; } } - if (!core_scroll_page(ui_text_verify_address, to_address, icp_send_error)) { + if (!core_scroll_page(ui_text_verify_account_id, to_account_id, icp_send_error)) { return false; } @@ -556,7 +553,7 @@ static bool get_user_verification_for_coin_txn(void) { char amount_string[30] = {'\0'}; double decimal_amount = (double)amount; decimal_amount *= 1e-8; - snprintf(amount_string, sizeof(amount_string), "%.8f", decimal_amount); + snprintf(amount_string, sizeof(amount_string), "%.*g", 8, decimal_amount); char display[100] = {'\0'}; snprintf(display, @@ -575,11 +572,12 @@ static bool get_user_verification_for_coin_txn(void) { char fee_string[30] = {'\0'}; double decimal_fee = (double)fee; decimal_fee *= 1e-8; - snprintf(fee_string, sizeof(fee_string), "%.8f", decimal_fee); + snprintf(fee_string, sizeof(fee_string), "%.*g", 8, decimal_fee); snprintf( - display, sizeof(display), UI_TEXT_SEND_TXN_FEE, fee_string, ICP_LUNIT); - if (!core_scroll_page(UI_TEXT_TXN_FEE, display, icp_send_error)) { + display, sizeof(display), UI_TEXT_VERIFY_FEE, fee_string, ICP_LUNIT); + + if (!core_confirmation(display, icp_send_error)) { return false; } diff --git a/src/constant_texts.c b/src/constant_texts.c index 5acea9683..92e8b2ac2 100644 --- a/src/constant_texts.c +++ b/src/constant_texts.c @@ -562,7 +562,8 @@ const char *ui_text_solana_verify_mint_authority = "Verify Token Address"; // ICP const char *ui_text_principal_id = "Principal Id"; const char *ui_text_account_id = "Account Id"; -const char *ui_text_verify_principal_id = "Verify recipient principal id"; +const char *ui_text_verify_principal_id = "Verify principal id"; +const char *ui_text_verify_account_id = "Verify account id"; #ifdef ALLOW_LOG_EXPORT const char *ui_text_send_logs_prompt = "Send logs to the cySync app?"; diff --git a/src/constant_texts.h b/src/constant_texts.h index bee2b83ad..8687b6b40 100644 --- a/src/constant_texts.h +++ b/src/constant_texts.h @@ -57,6 +57,7 @@ #define UI_TEXT_VERIFY_DESTINATION_TAG "Verify Destination Tag\n%lu" #define UI_TEXT_VERIFY_PRIORITY_FEE "Verify Priority Fee\n%s\n%s" #define UI_TEXT_VERIFY_MEMO "Verify Memo\n%s" +#define UI_TEXT_VERIFY_FEE "Verify Fee\n%s\n%s" // product hash extern const char *product_hash; @@ -399,6 +400,7 @@ extern const char *ui_text_inheritance_decryption_flow_failure; extern const char *ui_text_principal_id; extern const char *ui_text_account_id; extern const char *ui_text_verify_principal_id; +extern const char *ui_text_verify_account_id; #ifdef ALLOW_LOG_EXPORT extern const char *ui_text_send_logs_prompt; From 959284dd81ccbf620f43739573b00c23ad1d52b1 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 17 Apr 2025 11:45:03 +0530 Subject: [PATCH 34/75] fix: Lvgl kern value --- common/lvgl/src/lv_font/lv_font_fmt_txt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lvgl/src/lv_font/lv_font_fmt_txt.c b/common/lvgl/src/lv_font/lv_font_fmt_txt.c index d491da1f8..4461b3584 100644 --- a/common/lvgl/src/lv_font/lv_font_fmt_txt.c +++ b/common/lvgl/src/lv_font/lv_font_fmt_txt.c @@ -205,7 +205,7 @@ static int8_t get_kern_value(const lv_font_t * font, uint32_t gid_left, uint32_t /*Kern classes*/ const lv_font_fmt_txt_kern_classes_t * kdsc = fdsc->kern_dsc; uint8_t left_class = kdsc->left_class_mapping[gid_left]; - uint8_t right_class = kdsc->left_class_mapping[gid_right]; + uint8_t right_class = kdsc->right_class_mapping[gid_right]; /* If class = 0, kerning not exist for that glyph * else got the value form `class_pair_values` 2D array*/ From a29879fac042e5e5007519ada544c3e0b31f2aa0 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 17 Apr 2025 11:56:49 +0530 Subject: [PATCH 35/75] fix: Code formatting --- apps/icp_app/icp_txn.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/icp_app/icp_txn.c b/apps/icp_app/icp_txn.c index 84a26b8f6..9e2dd4618 100644 --- a/apps/icp_app/icp_txn.c +++ b/apps/icp_app/icp_txn.c @@ -497,9 +497,12 @@ static bool get_user_verification_for_token_txn(void) { return false; } - snprintf( - display_fee, sizeof(display_fee), UI_TEXT_VERIFY_FEE, fee_decimal_string, token.symbol); - + snprintf(display_fee, + sizeof(display_fee), + UI_TEXT_VERIFY_FEE, + fee_decimal_string, + token.symbol); + if (!core_confirmation(display_fee, icp_send_error)) { return false; } @@ -543,7 +546,8 @@ static bool get_user_verification_for_coin_txn(void) { } } - if (!core_scroll_page(ui_text_verify_account_id, to_account_id, icp_send_error)) { + if (!core_scroll_page( + ui_text_verify_account_id, to_account_id, icp_send_error)) { return false; } @@ -574,8 +578,7 @@ static bool get_user_verification_for_coin_txn(void) { decimal_fee *= 1e-8; snprintf(fee_string, sizeof(fee_string), "%.*g", 8, decimal_fee); - snprintf( - display, sizeof(display), UI_TEXT_VERIFY_FEE, fee_string, ICP_LUNIT); + snprintf(display, sizeof(display), UI_TEXT_VERIFY_FEE, fee_string, ICP_LUNIT); if (!core_confirmation(display, icp_send_error)) { return false; From 14c17a8de842b134f3902c828f1c862efc300844 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Sat, 19 Apr 2025 19:59:00 +0530 Subject: [PATCH 36/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6bf409f20..e2e08fe80 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:001 +firmware version=000:006:008:002 hardware version=000:001:000:000 magic number=45227A01 From d87f20aebe52c87ec925463c0949bfc0e47eea68 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 24 Apr 2025 14:35:41 +0530 Subject: [PATCH 37/75] chore: Version bump for dev release --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index e2e08fe80..12407a455 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:002 +firmware version=000:006:008:003 hardware version=000:001:000:000 magic number=45227A01 From 23ed8655dd7414791ac6829078b8b1f5766bc133 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Fri, 25 Apr 2025 19:20:46 +0530 Subject: [PATCH 38/75] feat: Added close swap flow functionality to exchange app --- apps/exchange_app/exchange_close_flow.c | 147 +++++++++++++++++++++ apps/exchange_app/exchange_initiate_flow.c | 3 + apps/exchange_app/exchange_main.c | 7 +- apps/exchange_app/exchange_priv.h | 10 ++ common/cypherock-common | 2 +- 5 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 apps/exchange_app/exchange_close_flow.c diff --git a/apps/exchange_app/exchange_close_flow.c b/apps/exchange_app/exchange_close_flow.c new file mode 100644 index 000000000..adb90250c --- /dev/null +++ b/apps/exchange_app/exchange_close_flow.c @@ -0,0 +1,147 @@ +/** + * @file close_flow.c + * @author Cypherock X1 Team + * @brief Closes the exhchange flow + * @copyright Copyright (c) 2023 HODL TECH PTE LTD + *
You may obtain a copy of license at https://mitcc.org/ + * + ****************************************************************************** + * @attention + * + * (c) Copyright 2023 by HODL TECH PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * "Commons Clause" License Condition v1.0 + * + * The Software is provided to you by the Licensor under the License, + * as defined below, subject to the following condition. + * + * Without limiting other conditions in the License, the grant of + * rights under the License will not include, and the License does not + * grant to you, the right to Sell the Software. + * + * For purposes of the foregoing, "Sell" means practicing any or all + * of the rights granted to you under the License to provide to third + * parties, for a fee or other consideration (including without + * limitation fees for hosting or consulting/ support services related + * to the Software), a product or service whose value derives, entirely + * or substantially, from the functionality of the Software. Any license + * notice or attribution required by the License must also include + * this Commons Clause License Condition notice. + * + * Software: All X1Wallet associated files. + * License: MIT + * Licensor: HODL TECH PTE LTD + * + ****************************************************************************** + */ + +/***************************************************************************** + * INCLUDES + *****************************************************************************/ + +#include + +#include "composable_app_queue.h" +#include "core_shared_context.h" +#include "exchange/close_flow.pb.h" +#include "exchange_api.h" +#include "ui_delay.h" + +/***************************************************************************** + * EXTERN VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE MACROS AND DEFINES + *****************************************************************************/ + +/***************************************************************************** + * PRIVATE TYPEDEFS + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTION PROTOTYPES + *****************************************************************************/ + +/** + * @brief Checks if the provided query contains expected request. + * @details The function performs the check on the request type and if the check + * fails, then it will send an error to the host exchange app and return false. + * + * @param query Reference to an instance of exchange_query_t containing query + * received from host app + * @param which_request The expected request type enum + * + * @return bool Indicating if the check succeeded or failed + * @retval true If the query contains the expected request + * @retval false If the query does not contain the expected request + */ +static bool check_which_request(const exchange_query_t *query, + pb_size_t which_request); + +/***************************************************************************** + * STATIC VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * GLOBAL VARIABLES + *****************************************************************************/ + +/***************************************************************************** + * STATIC FUNCTIONS + *****************************************************************************/ + +static bool check_which_request(const exchange_query_t *query, + pb_size_t which_request) { + if (which_request != query->close_flow.which_request) { + exchange_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, + ERROR_DATA_FLOW_INVALID_REQUEST); + return false; + } + + return true; +} + +/***************************************************************************** + * GLOBAL FUNCTIONS + *****************************************************************************/ + +void exchange_close_flow(exchange_query_t *query) { + exchange_result_t result = + init_exchange_result(EXCHANGE_RESULT_CLOSE_FLOW_TAG); + if (!check_which_request(query, EXCHANGE_CLOSE_FLOW_REQUEST_CLOSE_TAG)) { + return; + } + + // Clear existing composable app queue + caq_clear(); + + // Clear shared context + core_clear_shared_context(); + + delay_scr_init("Swap flow closed", DELAY_TIME); + + result.close_flow.which_response = EXCHANGE_CLOSE_FLOW_RESPONSE_RESULT_TAG; + exchange_send_result(&result); +} diff --git a/apps/exchange_app/exchange_initiate_flow.c b/apps/exchange_app/exchange_initiate_flow.c index eccf54ae3..55f4a262e 100644 --- a/apps/exchange_app/exchange_initiate_flow.c +++ b/apps/exchange_app/exchange_initiate_flow.c @@ -68,6 +68,7 @@ #include "exchange_context.h" #include "exchange_main.h" #include "memzero.h" +#include "ui_delay.h" /***************************************************************************** * EXTERN VARIABLES @@ -139,6 +140,8 @@ void exchange_initiate_flow(exchange_query_t *query) { // Clear existing composable app queue caq_clear(); + delay_scr_init("Swap flow initiated", DELAY_TIME); + // Receive flow { caq_node_data_t data = {.applet_id = diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index 386d040f5..8450bea34 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -171,6 +171,10 @@ void exchange_main(usb_event_t usb_evt, const void *app_config) { exchange_store_signature(&query); break; } + case EXCHANGE_QUERY_CLOSE_FLOW_TAG: { + exchange_close_flow(&query); + break; + } default: { /* In case we ever encounter invalid query, convey to the host app */ exchange_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG, @@ -195,9 +199,6 @@ bool exchange_app_validate_caq(caq_node_data_t data) { if (caq_data.applet_id == data.applet_id && memcmp(caq_data.params, data.params, sizeof(data.params)) == 0) { - if (caq_data.applet_id != exchange_app_desc.id) { - delay_scr_init("Swap", DELAY_SHORT); - } { char hex_arr[500] = {0}; char title[100] = {0}; diff --git a/apps/exchange_app/exchange_priv.h b/apps/exchange_app/exchange_priv.h index da3f5f306..eebe83551 100644 --- a/apps/exchange_app/exchange_priv.h +++ b/apps/exchange_app/exchange_priv.h @@ -72,4 +72,14 @@ void exchange_get_signature(exchange_query_t *query); */ void exchange_store_signature(exchange_query_t *query); +/** + * @brief Closes the exchange flow by clearing the composable app + * queue and shared context. + * + * This function clears the existing queue, and the shared context. + * + * @param query Pointer to the exchange query structure. + */ +void exchange_close_flow(exchange_query_t *query); + #endif diff --git a/common/cypherock-common b/common/cypherock-common index 80008c3b3..0d8a6c51d 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit 80008c3b3d249ba03515f9028de83ea55382ad2e +Subproject commit 0d8a6c51d051bf71d7b4ef7dc55413d576176fcf From b6584126e738754b4a767a9eaeaadd197893cdde Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Mon, 28 Apr 2025 15:33:58 +0530 Subject: [PATCH 39/75] fix: Null title check in core scroll page --- apps/exchange_app/exchange_main.c | 2 +- common/interfaces/user_interface/ui_scroll_page.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index 8450bea34..d6482e741 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -204,7 +204,7 @@ bool exchange_app_validate_caq(caq_node_data_t data) { char title[100] = {0}; snprintf(title, 100, "%ld", data.applet_id); byte_array_to_hex_string(data.params, 40, hex_arr, 100); - LOG_ERROR("Match %s [%s]", title, hex_arr); + LOG_INFO("Match %s [%s]", title, hex_arr); } caq_pop(); diff --git a/common/interfaces/user_interface/ui_scroll_page.c b/common/interfaces/user_interface/ui_scroll_page.c index baa7d914f..0ee048345 100644 --- a/common/interfaces/user_interface/ui_scroll_page.c +++ b/common/interfaces/user_interface/ui_scroll_page.c @@ -261,8 +261,10 @@ static void page_update_header(void) { gp_scrollabe_page_lvgl->p_ui_page_lvgl, 128, scroll_page_height); lv_obj_align( gp_scrollabe_page_lvgl->p_ui_page_lvgl, NULL, scroll_page_aligment, 0, 0); - lv_obj_set_hidden(gp_scrollabe_page_lvgl->p_ui_header_lvgl, - is_heading_hidden); + if (gp_scrollabe_page_lvgl->p_ui_header_lvgl != NULL) { + lv_obj_set_hidden(gp_scrollabe_page_lvgl->p_ui_header_lvgl, + is_heading_hidden); + } } static void page_update_footnote(void) { From 48d076520f8a0be7043fc0d2cf096d7b2c75bfa0 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Mon, 28 Apr 2025 15:34:47 +0530 Subject: [PATCH 40/75] chore: Version bump for dev release --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 12407a455..052a2089d 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:003 +firmware version=000:006:008:004 hardware version=000:001:000:000 magic number=45227A01 From a5de5a4b9a0a9206a660d8fd2b9092444e747e6b Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 29 Apr 2025 09:42:54 +0530 Subject: [PATCH 41/75] fix: Corrected send wallet id in exchange app --- apps/exchange_app/exchange_initiate_flow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/exchange_app/exchange_initiate_flow.c b/apps/exchange_app/exchange_initiate_flow.c index 55f4a262e..c1d81fe7c 100644 --- a/apps/exchange_app/exchange_initiate_flow.c +++ b/apps/exchange_app/exchange_initiate_flow.c @@ -183,8 +183,8 @@ void exchange_initiate_flow(exchange_query_t *query) { memzero(data.params, sizeof(data.params)); memcpy(data.params, - query->initiate_flow.initiate.to.wallet_id, - sizeof(query->initiate_flow.initiate.to.wallet_id)); + query->initiate_flow.initiate.from.wallet_id, + sizeof(query->initiate_flow.initiate.from.wallet_id)); data.params[32] = EXCHANGE_FLOW_TAG_SEND; caq_push(data); From d3c0e838a23c1b689716da8ad6b475605e77a614 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 29 Apr 2025 09:43:39 +0530 Subject: [PATCH 42/75] chore: Version bump for dev release --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 052a2089d..3b407b6e6 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:004 +firmware version=000:006:008:005 hardware version=000:001:000:000 magic number=45227A01 From fbc1dee28c8f9d5db0bae67e3861e658162fcd69 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 29 Apr 2025 10:51:55 +0530 Subject: [PATCH 43/75] chore: Version bump for dev release --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 3b407b6e6..34ea74159 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:005 +firmware version=000:006:008:006 hardware version=000:001:000:000 magic number=45227A01 From 372f5e945140a6938be3e4ad5d7329b27da585cc Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 29 Apr 2025 12:05:29 +0530 Subject: [PATCH 44/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 34ea74159..fadd9b5c0 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:006 +firmware version=000:006:008:007 hardware version=000:001:000:000 magic number=45227A01 From c4dab6fe273f90ee22011fd95eed4c50e50df634 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 8 May 2025 14:11:50 +0530 Subject: [PATCH 45/75] fix: Code formatting --- apps/icp_app/icp_txn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/icp_app/icp_txn.c b/apps/icp_app/icp_txn.c index 9e2dd4618..78bd4a643 100644 --- a/apps/icp_app/icp_txn.c +++ b/apps/icp_app/icp_txn.c @@ -541,7 +541,8 @@ static bool get_user_verification_for_coin_txn(void) { ICP_ACCOUNT_ID_LENGTH * 2 + 1); if (use_signature_verification) { - if (!exchange_validate_stored_signature(to_account_id, sizeof(to_account_id))) { + if (!exchange_validate_stored_signature(to_account_id, + sizeof(to_account_id))) { return false; } } From 3590ea6d10bc47838c6470c52e3cd2b25ebb4e66 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 8 May 2025 19:56:38 +0530 Subject: [PATCH 46/75] fix: Length validation in apdu exchange --- common/interfaces/card_interface/nfc.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/common/interfaces/card_interface/nfc.c b/common/interfaces/card_interface/nfc.c index 3ff3090b0..fbadc3800 100644 --- a/common/interfaces/card_interface/nfc.c +++ b/common/interfaces/card_interface/nfc.c @@ -669,6 +669,9 @@ ret_code_t nfc_exchange_apdu(uint8_t *send_apdu, ASSERT(recv_len != NULL); ASSERT(send_len != 0); + uint8_t expected_recv_len = *recv_len; + *recv_len = 0; + ret_code_t err_code = adafruit_diagnose_card_presence(); if (err_code != 0) return NFC_CARD_ABSENT; @@ -693,8 +696,10 @@ ret_code_t nfc_exchange_apdu(uint8_t *send_apdu, total_packets = ceil(send_len / (1.0 * SEND_PACKET_MAX_LEN)); for (int packet = 1; packet <= total_packets;) { - recv_pkt_len = RECV_PACKET_MAX_ENC_LEN; /* On every request set acceptable - packet length */ + recv_pkt_len = RECV_PACKET_MAX_ENC_LEN <= expected_recv_len + ? RECV_PACKET_MAX_ENC_LEN + : expected_recv_len; /* On every request set acceptable + packet length */ /** * Sets appropriate CLA byte for each packet. CLA byte (first byte of @@ -757,11 +762,14 @@ ret_code_t nfc_exchange_apdu(uint8_t *send_apdu, /** Prepare to request next packet from the card */ *recv_len = recv_pkt_len; - recv_pkt_len = RECV_PACKET_MAX_ENC_LEN; + uint8_t remaining_recv_len = expected_recv_len - *recv_len + 2; + recv_pkt_len = RECV_PACKET_MAX_ENC_LEN <= remaining_recv_len + ? RECV_PACKET_MAX_ENC_LEN + : remaining_recv_len; request_chain_pkt[2] = ceil(*recv_len * 1.0 / RECV_PACKET_MAX_LEN); /** Request all the remaining packets of multi-packet response */ - while (recv_apdu[*recv_len - 2] == 0x61) { + while (recv_apdu[*recv_len - 2] == 0x61 && recv_pkt_len > 0) { *recv_len -= 2; err_code = adafruit_pn532_in_data_exchange(request_chain_pkt, sizeof(request_chain_pkt), @@ -787,7 +795,10 @@ ret_code_t nfc_exchange_apdu(uint8_t *send_apdu, /** Prepare to request next packet from the card */ *recv_len += recv_pkt_len; - recv_pkt_len = RECV_PACKET_MAX_ENC_LEN; + remaining_recv_len = expected_recv_len - *recv_len + 2; + recv_pkt_len = RECV_PACKET_MAX_ENC_LEN <= remaining_recv_len + ? RECV_PACKET_MAX_ENC_LEN + : remaining_recv_len; request_chain_pkt[2] = *recv_len / RECV_PACKET_MAX_LEN + 1; } From efd20492bb149638317b21c7b00eddad3eaa1b01 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 8 May 2025 20:14:17 +0530 Subject: [PATCH 47/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index e2e08fe80..b27c06771 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:002 +firmware version=000:006:008:008 hardware version=000:001:000:000 magic number=45227A01 From 3eea41a3bf3016a6010ac9c25b61ff35ae89f5ef Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Fri, 9 May 2025 11:17:23 +0530 Subject: [PATCH 48/75] fix: Added logs for signature invalidation --- apps/exchange_app/exchange_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index d6482e741..fad9ddf28 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -252,6 +252,16 @@ bool exchange_validate_stored_signature(char *receiver, 0) { delay_scr_init("Failed to validate signature\n Do not proceed with Swap", DELAY_TIME); + + { + char hex_arr[500] = {0}; + char title[500] = {0}; + byte_array_to_hex_string(sig, 64, title, 200); + byte_array_to_hex_string( + server_verification_pub_key, SESSION_PUB_KEY_SIZE, hex_arr, 200); + LOG_ERROR("CAQ Signature: [%s]", title); + LOG_ERROR("CAQ Data received: [%s] [%s]", hex_arr, receiver); + } return false; } return true; From 29f47008c0c39aa94ddfdba55ebd02db919973d6 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Fri, 9 May 2025 11:17:51 +0530 Subject: [PATCH 49/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index fadd9b5c0..4ac4821e6 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:007 +firmware version=000:006:008:009 hardware version=000:001:000:000 magic number=45227A01 From 662bdaf55136a3dbe7a4a2712606c1e7a2c0919c Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Mon, 12 May 2025 12:27:13 +0530 Subject: [PATCH 50/75] fix: Correct logs for sig verification, made test changes for lvgl issue --- apps/exchange_app/exchange_get_signature.c | 1 + apps/exchange_app/exchange_main.c | 22 +++++++++++++------- apps/exchange_app/exchange_store_signature.c | 1 + 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/apps/exchange_app/exchange_get_signature.c b/apps/exchange_app/exchange_get_signature.c index 06b77d279..d681b49fb 100644 --- a/apps/exchange_app/exchange_get_signature.c +++ b/apps/exchange_app/exchange_get_signature.c @@ -140,6 +140,7 @@ void exchange_get_signature(exchange_query_t *query) { EXCHANGE_GET_SIGNATURE_REQUEST_INITIATE_TAG)) { return; } + caq_pop(); result.get_signature.which_response = EXCHANGE_GET_SIGNATURE_RESPONSE_RESULT_TAG; diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index fad9ddf28..cf78a5dd2 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -207,7 +207,7 @@ bool exchange_app_validate_caq(caq_node_data_t data) { LOG_INFO("Match %s [%s]", title, hex_arr); } - caq_pop(); + // caq_pop(); return true; } @@ -244,9 +244,12 @@ bool exchange_validate_stored_signature(char *receiver, derive_server_public_key(server_verification_pub_key); size_t len = strnlen(receiver, receiver_max_size); + char recv_addr[len]; + strncpy(recv_addr, receiver, len); + uint8_t hash[SHA256_DIGEST_LENGTH] = {0}; - sha256_Raw((uint8_t *)receiver, len, hash); + sha256_Raw((uint8_t *)recv_addr, len, hash); if (ecdsa_verify_digest(&nist256p1, server_verification_pub_key, sig, hash) != 0) { @@ -254,16 +257,18 @@ bool exchange_validate_stored_signature(char *receiver, DELAY_TIME); { - char hex_arr[500] = {0}; - char title[500] = {0}; - byte_array_to_hex_string(sig, 64, title, 200); + char signature[500] = {0}; + byte_array_to_hex_string(sig, 64, signature, 200); + LOG_ERROR("CAQ Signature: [%s]", signature); + + char pubkey[500] = {0}; byte_array_to_hex_string( - server_verification_pub_key, SESSION_PUB_KEY_SIZE, hex_arr, 200); - LOG_ERROR("CAQ Signature: [%s]", title); - LOG_ERROR("CAQ Data received: [%s] [%s]", hex_arr, receiver); + server_verification_pub_key, SESSION_PUB_KEY_SIZE, pubkey, 200); + LOG_ERROR("CAQ Data received: [%s] [%s]", pubkey, recv_addr); } return false; } + caq_pop(); return true; } @@ -283,4 +288,5 @@ void exchange_sign_address(char *address, size_t address_max_size) { memcpy(shared_context + offset, data.postfix2, sizeof(data.postfix2)); offset += sizeof(data.postfix2); + caq_pop(); } diff --git a/apps/exchange_app/exchange_store_signature.c b/apps/exchange_app/exchange_store_signature.c index 517f40598..8bed77b82 100644 --- a/apps/exchange_app/exchange_store_signature.c +++ b/apps/exchange_app/exchange_store_signature.c @@ -142,6 +142,7 @@ void exchange_store_signature(exchange_query_t *query) { EXCHANGE_STORE_SIGNATURE_REQUEST_INITIATE_TAG)) { return; } + caq_pop(); core_clear_shared_context(); From bbe73e5c6cf85e1a4788b27c9d023fcd42375051 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Mon, 12 May 2025 12:33:05 +0530 Subject: [PATCH 51/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 4ac4821e6..0c8d145df 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:009 +firmware version=000:006:008:010 hardware version=000:001:000:000 magic number=45227A01 From d5f36c5e9604225fab4fd3345d7db964cc5de5fa Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Mon, 12 May 2025 18:11:58 +0530 Subject: [PATCH 52/75] revert: Test changes for lvgl issue --- apps/exchange_app/exchange_get_signature.c | 1 - apps/exchange_app/exchange_main.c | 5 ++--- apps/exchange_app/exchange_store_signature.c | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/exchange_app/exchange_get_signature.c b/apps/exchange_app/exchange_get_signature.c index d681b49fb..06b77d279 100644 --- a/apps/exchange_app/exchange_get_signature.c +++ b/apps/exchange_app/exchange_get_signature.c @@ -140,7 +140,6 @@ void exchange_get_signature(exchange_query_t *query) { EXCHANGE_GET_SIGNATURE_REQUEST_INITIATE_TAG)) { return; } - caq_pop(); result.get_signature.which_response = EXCHANGE_GET_SIGNATURE_RESPONSE_RESULT_TAG; diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index cf78a5dd2..b6368514a 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -207,7 +207,7 @@ bool exchange_app_validate_caq(caq_node_data_t data) { LOG_INFO("Match %s [%s]", title, hex_arr); } - // caq_pop(); + caq_pop(); return true; } @@ -268,7 +268,7 @@ bool exchange_validate_stored_signature(char *receiver, } return false; } - caq_pop(); + return true; } @@ -288,5 +288,4 @@ void exchange_sign_address(char *address, size_t address_max_size) { memcpy(shared_context + offset, data.postfix2, sizeof(data.postfix2)); offset += sizeof(data.postfix2); - caq_pop(); } diff --git a/apps/exchange_app/exchange_store_signature.c b/apps/exchange_app/exchange_store_signature.c index 8bed77b82..517f40598 100644 --- a/apps/exchange_app/exchange_store_signature.c +++ b/apps/exchange_app/exchange_store_signature.c @@ -142,7 +142,6 @@ void exchange_store_signature(exchange_query_t *query) { EXCHANGE_STORE_SIGNATURE_REQUEST_INITIATE_TAG)) { return; } - caq_pop(); core_clear_shared_context(); From 7cf258abdd093d9ca3a767c1c3fa89461dd50306 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 13 May 2025 17:33:21 +0530 Subject: [PATCH 53/75] fix: Scroll page bug --- common/interfaces/user_interface/ui_scroll_page.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/interfaces/user_interface/ui_scroll_page.c b/common/interfaces/user_interface/ui_scroll_page.c index 0ee048345..b0d67a157 100644 --- a/common/interfaces/user_interface/ui_scroll_page.c +++ b/common/interfaces/user_interface/ui_scroll_page.c @@ -680,7 +680,8 @@ static void ui_scrollable_page_create(void) { /** * Recalculate the total pages if heading is only visible on the first page */ - if (gp_scrollabe_page_data->bool_only_first_page_header_visible) { + if (NULL != gp_scrollabe_page_data->p_ui_heading && + gp_scrollabe_page_data->bool_only_first_page_header_visible) { gp_scrollabe_page_data->total_page_num = 1; int16_t first_page_height = currPageHeight; From 0f1b07e85a71460db8efdca10d005e36534d1cee Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 14 May 2025 11:43:24 +0530 Subject: [PATCH 54/75] fix: Swap signature verification in solana token txn --- apps/icp_app/icp_txn.c | 7 +++++++ apps/solana_app/solana_sign_txn.c | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/apps/icp_app/icp_txn.c b/apps/icp_app/icp_txn.c index 78bd4a643..2ed54807e 100644 --- a/apps/icp_app/icp_txn.c +++ b/apps/icp_app/icp_txn.c @@ -443,6 +443,13 @@ static bool get_user_verification_for_token_txn(void) { get_principal_id_to_display( decoded_utxn->to.owner, ICP_PRINCIPAL_LENGTH, principal_id); + if (use_signature_verification) { + if (!exchange_validate_stored_signature(principal_id, + sizeof(principal_id))) { + return false; + } + } + // Now take user verification if (!core_scroll_page( ui_text_verify_principal_id, principal_id, icp_send_error)) { diff --git a/apps/solana_app/solana_sign_txn.c b/apps/solana_app/solana_sign_txn.c index 3c34e762c..b72e3be09 100644 --- a/apps/solana_app/solana_sign_txn.c +++ b/apps/solana_app/solana_sign_txn.c @@ -691,6 +691,12 @@ static bool verify_solana_transfer_token_transaction() { return false; } + if (use_signature_verification) { + if (!exchange_validate_stored_signature(address, sizeof(address))) { + return false; + } + } + // Now take user verification if (!core_scroll_page(ui_text_verify_address, address, solana_send_error)) { return false; From 93d7fe3582b6b5caed99b2babb8c54336ca1e185 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 14 May 2025 11:48:46 +0530 Subject: [PATCH 55/75] fix: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 0c8d145df..1a775d918 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:010 +firmware version=000:006:008:011 hardware version=000:001:000:000 magic number=45227A01 From 47b62cdbf30ca7285d315cb175a81893ac4a66f8 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Sat, 17 May 2025 14:36:52 +0530 Subject: [PATCH 56/75] fix: Commented swap signature verification logs --- apps/exchange_app/exchange_main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index b6368514a..0cb810df2 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -256,16 +256,16 @@ bool exchange_validate_stored_signature(char *receiver, delay_scr_init("Failed to validate signature\n Do not proceed with Swap", DELAY_TIME); - { - char signature[500] = {0}; - byte_array_to_hex_string(sig, 64, signature, 200); - LOG_ERROR("CAQ Signature: [%s]", signature); - - char pubkey[500] = {0}; - byte_array_to_hex_string( - server_verification_pub_key, SESSION_PUB_KEY_SIZE, pubkey, 200); - LOG_ERROR("CAQ Data received: [%s] [%s]", pubkey, recv_addr); - } + // { + // char signature[500] = {0}; + // byte_array_to_hex_string(sig, 64, signature, 200); + // LOG_ERROR("CAQ Signature: [%s]", signature); + + // char pubkey[500] = {0}; + // byte_array_to_hex_string( + // server_verification_pub_key, SESSION_PUB_KEY_SIZE, pubkey, 200); + // LOG_ERROR("CAQ Data received: [%s] [%s]", pubkey, recv_addr); + // } return false; } From cd9f5550875a594099cbbb53bbc99696f580deb1 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Sat, 17 May 2025 14:37:27 +0530 Subject: [PATCH 57/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 1a775d918..e36db7f75 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:011 +firmware version=000:006:008:012 hardware version=000:001:000:000 magic number=45227A01 From c3c2cae5161a749124777d5193e4ff60d3c01b11 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Mon, 19 May 2025 13:16:29 +0530 Subject: [PATCH 58/75] fix: Removed commented code --- apps/exchange_app/exchange_main.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/apps/exchange_app/exchange_main.c b/apps/exchange_app/exchange_main.c index 0cb810df2..59c29e5c6 100644 --- a/apps/exchange_app/exchange_main.c +++ b/apps/exchange_app/exchange_main.c @@ -256,16 +256,6 @@ bool exchange_validate_stored_signature(char *receiver, delay_scr_init("Failed to validate signature\n Do not proceed with Swap", DELAY_TIME); - // { - // char signature[500] = {0}; - // byte_array_to_hex_string(sig, 64, signature, 200); - // LOG_ERROR("CAQ Signature: [%s]", signature); - - // char pubkey[500] = {0}; - // byte_array_to_hex_string( - // server_verification_pub_key, SESSION_PUB_KEY_SIZE, pubkey, 200); - // LOG_ERROR("CAQ Data received: [%s] [%s]", pubkey, recv_addr); - // } return false; } From 9e418743ea90fb5614966183cbc0a5d666c86b82 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Mon, 19 May 2025 13:18:02 +0530 Subject: [PATCH 59/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index e36db7f75..a92b76610 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:008:012 +firmware version=000:006:009:000 hardware version=000:001:000:000 magic number=45227A01 From 88899be890bc4c87576880f5a4d161fb8d1a8e7a Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 20 May 2025 17:00:59 +0530 Subject: [PATCH 60/75] fix: Code formatting --- common/interfaces/card_interface/nfc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/common/interfaces/card_interface/nfc.c b/common/interfaces/card_interface/nfc.c index fbadc3800..a9c4146a9 100644 --- a/common/interfaces/card_interface/nfc.c +++ b/common/interfaces/card_interface/nfc.c @@ -697,9 +697,9 @@ ret_code_t nfc_exchange_apdu(uint8_t *send_apdu, total_packets = ceil(send_len / (1.0 * SEND_PACKET_MAX_LEN)); for (int packet = 1; packet <= total_packets;) { recv_pkt_len = RECV_PACKET_MAX_ENC_LEN <= expected_recv_len - ? RECV_PACKET_MAX_ENC_LEN - : expected_recv_len; /* On every request set acceptable - packet length */ + ? RECV_PACKET_MAX_ENC_LEN + : expected_recv_len; /* On every request set acceptable + packet length */ /** * Sets appropriate CLA byte for each packet. CLA byte (first byte of @@ -764,8 +764,8 @@ ret_code_t nfc_exchange_apdu(uint8_t *send_apdu, *recv_len = recv_pkt_len; uint8_t remaining_recv_len = expected_recv_len - *recv_len + 2; recv_pkt_len = RECV_PACKET_MAX_ENC_LEN <= remaining_recv_len - ? RECV_PACKET_MAX_ENC_LEN - : remaining_recv_len; + ? RECV_PACKET_MAX_ENC_LEN + : remaining_recv_len; request_chain_pkt[2] = ceil(*recv_len * 1.0 / RECV_PACKET_MAX_LEN); /** Request all the remaining packets of multi-packet response */ @@ -797,8 +797,8 @@ ret_code_t nfc_exchange_apdu(uint8_t *send_apdu, *recv_len += recv_pkt_len; remaining_recv_len = expected_recv_len - *recv_len + 2; recv_pkt_len = RECV_PACKET_MAX_ENC_LEN <= remaining_recv_len - ? RECV_PACKET_MAX_ENC_LEN - : remaining_recv_len; + ? RECV_PACKET_MAX_ENC_LEN + : remaining_recv_len; request_chain_pkt[2] = *recv_len / RECV_PACKET_MAX_LEN + 1; } From 91753e4a4d657150b39261f7021300b94adea6f8 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Tue, 20 May 2025 17:25:47 +0530 Subject: [PATCH 61/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index a92b76610..3895a1273 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:009:000 +firmware version=000:006:009:001 hardware version=000:001:000:000 magic number=45227A01 From de02c6da5ce46beb48a68599c230a14c21c25bf2 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Wed, 21 May 2025 23:24:05 +0530 Subject: [PATCH 62/75] fix: Unit tests --- common/core/composable_app_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/core/composable_app_queue.c b/common/core/composable_app_queue.c index ad44ee713..17c96520c 100644 --- a/common/core/composable_app_queue.c +++ b/common/core/composable_app_queue.c @@ -27,7 +27,7 @@ static composable_app_queue_t *caq_create_queue() { } bool caq_is_empty() { - return (composable_app_queue->count == 0); + return (composable_app_queue == NULL || composable_app_queue->count == 0); } void caq_push(caq_node_data_t data) { From 99d6ebcd96c37e43371b15c7efaecbae44be91c6 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 22 May 2025 12:07:19 +0530 Subject: [PATCH 63/75] chore: Updated cypherock common submodule --- common/cypherock-common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cypherock-common b/common/cypherock-common index 0e7d09873..67a0d07b7 160000 --- a/common/cypherock-common +++ b/common/cypherock-common @@ -1 +1 @@ -Subproject commit 0e7d0987335a1707e2ca74faed8e540dc36d059a +Subproject commit 67a0d07b71c8041558ca7c0d19e7dff9d4153677 From 9a42b4a4fd944f83f32cd234cb3bdc4512542d0d Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 22 May 2025 13:37:26 +0530 Subject: [PATCH 64/75] feat: Added swap functionality to constellation app --- .../constellation_app/constellation_pub_key.c | 17 ++++++++++++++- apps/constellation_app/constellation_txn.c | 21 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/apps/constellation_app/constellation_pub_key.c b/apps/constellation_app/constellation_pub_key.c index b8d89f405..43bfe56fa 100644 --- a/apps/constellation_app/constellation_pub_key.c +++ b/apps/constellation_app/constellation_pub_key.c @@ -66,12 +66,14 @@ #include "base58.h" #include "bip32.h" #include "coin_utils.h" +#include "composable_app_queue.h" #include "constellation_api.h" #include "constellation_context.h" #include "constellation_helpers.h" #include "constellation_priv.h" #include "curves.h" #include "ecdsa.h" +#include "exchange_main.h" #include "hasher.h" #include "reconstruct_wallet_flow.h" #include "secp256k1.h" @@ -222,7 +224,8 @@ static bool get_user_consent(const pb_size_t which_request, /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ - + static bool sign_address = false; + /// Ref: /// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/key-store.ts#L39 static const uint8_t PKCS_PREFIX[PKCS_PREFIX_SIZE] = { @@ -274,6 +277,14 @@ static bool validate_request( } } + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, req->wallet_id, sizeof(req->wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_RECEIVE; + + sign_address = exchange_app_validate_caq(data); + return status; } @@ -500,6 +511,10 @@ void constellation_get_pub_keys(constellation_query_t *query) { return; } + if (sign_address) { + exchange_sign_address(address, sizeof(address)); + } + if (!core_scroll_page( ui_text_receive_on, address, constellation_send_error)) { return; diff --git a/apps/constellation_app/constellation_txn.c b/apps/constellation_app/constellation_txn.c index 73bffbb87..78788c21b 100644 --- a/apps/constellation_app/constellation_txn.c +++ b/apps/constellation_app/constellation_txn.c @@ -66,12 +66,14 @@ #include #include "coin_utils.h" +#include "composable_app_queue.h" #include "constellation/core.pb.h" #include "constellation/sign_txn.pb.h" #include "constellation_api.h" #include "constellation_context.h" #include "constellation_helpers.h" #include "constellation_priv.h" +#include "exchange_main.h" #include "reconstruct_wallet_flow.h" #include "status_api.h" #include "ui_core_confirm.h" @@ -205,6 +207,7 @@ static bool send_signature(constellation_query_t *query, * STATIC VARIABLES *****************************************************************************/ static constellation_txn_context_t *constellation_txn_context = NULL; +static bool use_signature_verification = false; /***************************************************************************** * GLOBAL VARIABLES @@ -242,6 +245,17 @@ static bool validate_request_data( ERROR_DATA_FLOW_INVALID_DATA); status = false; } + + caq_node_data_t data = {.applet_id = get_applet_id()}; + + memzero(data.params, sizeof(data.params)); + memcpy(data.params, + request->initiate.wallet_id, + sizeof(request->initiate.wallet_id)); + data.params[32] = EXCHANGE_FLOW_TAG_SEND; + + use_signature_verification = exchange_app_validate_caq(data); + return status; } @@ -305,6 +319,13 @@ static bool fetch_valid_input(constellation_query_t *query) { static bool get_user_verification(void) { const constellation_transaction_t *txn = constellation_txn_context->txn; + if (use_signature_verification) { + if (!exchange_validate_stored_signature((char *)txn->destination, + sizeof(txn->destination))) { + return false; + } + } + // verify recipient address if (!core_scroll_page( ui_text_verify_address, txn->destination, constellation_send_error)) { From 8f632d45f8ce194d7d86317719e4011a1ea46ef4 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 22 May 2025 19:53:17 +0530 Subject: [PATCH 65/75] fix: Updated app versions count to allow more apps --- common/proto-options/version.options | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/proto-options/version.options b/common/proto-options/version.options index ecd5a1261..c90ddf0d8 100644 --- a/common/proto-options/version.options +++ b/common/proto-options/version.options @@ -1,2 +1,2 @@ # Options for file common/cypherock-common/proto/version.proto -core.AppVersionResultResponse.app_versions type:FT_STATIC max_count:20 +core.AppVersionResultResponse.app_versions type:FT_STATIC max_count:25 From 8603b46cfda2900c7975c602167253c4cd6435a4 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 22 May 2025 19:57:29 +0530 Subject: [PATCH 66/75] fix: Code formatting --- apps/constellation_app/constellation_pub_key.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/constellation_app/constellation_pub_key.c b/apps/constellation_app/constellation_pub_key.c index 43bfe56fa..4435f3d22 100644 --- a/apps/constellation_app/constellation_pub_key.c +++ b/apps/constellation_app/constellation_pub_key.c @@ -224,8 +224,8 @@ static bool get_user_consent(const pb_size_t which_request, /***************************************************************************** * STATIC VARIABLES *****************************************************************************/ - static bool sign_address = false; - +static bool sign_address = false; + /// Ref: /// https://github.com/StardustCollective/dag4.js/blob/main/packages/dag4-keystore/src/key-store.ts#L39 static const uint8_t PKCS_PREFIX[PKCS_PREFIX_SIZE] = { From 5aec696ca74c9810b25a96baa75fbe96d1c6a0d9 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 22 May 2025 20:09:34 +0530 Subject: [PATCH 67/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 3895a1273..d3352252b 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:009:001 +firmware version=000:006:010:000 hardware version=000:001:000:000 magic number=45227A01 From 0969bd99e804712b18737c5d978752789079c6b4 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 29 May 2025 16:32:08 +0530 Subject: [PATCH 68/75] fix: Invalid signature in constellation sign msg --- apps/constellation_app/constellation_sign_msg.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index d16301a8c..6314db618 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -63,6 +63,7 @@ #include #include +#include #include "atca_helpers.h" #include "atca_status.h" @@ -428,14 +429,16 @@ static size_t constellation_get_prefixed_msg_data( size_t msg_len = ctx->init.message_size; char length_string[20] = ""; - size_t length_string_len = - snprintf(length_string, sizeof(length_string), "%zu\n", msg_len); + size_t length_string_len = sprintf(length_string, "%zu\n", msg_len); size_t total_len = prefix_len + length_string_len + msg_len; - strncpy(prefixed_msg_data, prefix, prefix_len); - strncat(prefixed_msg_data, length_string, length_string_len); - strncat(prefixed_msg_data, (const char *)ctx->msg_data, msg_len); + snprintf(prefixed_msg_data, + total_len + 1, // +1 for \0 + "%s%s%s", + prefix, + length_string, + (const char *)ctx->msg_data); return total_len; } From 6e9c454f93ccd803b174be01d1aaccaa6c8006e7 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 29 May 2025 16:40:30 +0530 Subject: [PATCH 69/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index d3352252b..3e901626c 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:010:000 +firmware version=000:006:010:001 hardware version=000:001:000:000 magic number=45227A01 From 717773105edfe423c841313ec053c02363808d68 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 29 May 2025 22:04:41 +0530 Subject: [PATCH 70/75] fix: Invalid constellation signature --- apps/constellation_app/constellation_sign_msg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index 6314db618..26737b7a8 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -427,9 +427,12 @@ static size_t constellation_get_prefixed_msg_data( size_t prefix_len, char *prefixed_msg_data) { size_t msg_len = ctx->init.message_size; + core_scroll_page("msg", (const char *)ctx->msg_data, NULL); + core_scroll_page("prefix", prefix, NULL); char length_string[20] = ""; size_t length_string_len = sprintf(length_string, "%zu\n", msg_len); + core_scroll_page("length_string", length_string, NULL); size_t total_len = prefix_len + length_string_len + msg_len; @@ -440,6 +443,7 @@ static size_t constellation_get_prefixed_msg_data( length_string, (const char *)ctx->msg_data); + core_scroll_page("prefixed_msg_data", prefixed_msg_data, NULL); return total_len; } From 6d56d07ebff96b36426ebcdce7e0d7d634c04a2b Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 29 May 2025 22:05:36 +0530 Subject: [PATCH 71/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 3e901626c..c6941ed58 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:010:001 +firmware version=000:006:010:002 hardware version=000:001:000:000 magic number=45227A01 From a705eed82c711402bc4585027236a0f4886353b8 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 29 May 2025 23:38:36 +0530 Subject: [PATCH 72/75] fix: Invalid constellation signature --- apps/constellation_app/constellation_sign_msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index 26737b7a8..3ba13b567 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -431,7 +431,7 @@ static size_t constellation_get_prefixed_msg_data( core_scroll_page("prefix", prefix, NULL); char length_string[20] = ""; - size_t length_string_len = sprintf(length_string, "%zu\n", msg_len); + size_t length_string_len = sprintf(length_string, "%u\n", msg_len); core_scroll_page("length_string", length_string, NULL); size_t total_len = prefix_len + length_string_len + msg_len; From f5330d255b0eeef01b814163b5db0096b89dc9ef Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 29 May 2025 23:39:48 +0530 Subject: [PATCH 73/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index c6941ed58..5f2b6de34 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:010:002 +firmware version=000:006:010:003 hardware version=000:001:000:000 magic number=45227A01 From 6f9d94cb0b463a4ff1748746e57d33865f5d3529 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Thu, 29 May 2025 23:52:19 +0530 Subject: [PATCH 74/75] fix: Removed unnecessary prints --- apps/constellation_app/constellation_sign_msg.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/constellation_app/constellation_sign_msg.c b/apps/constellation_app/constellation_sign_msg.c index 3ba13b567..a01610b0c 100644 --- a/apps/constellation_app/constellation_sign_msg.c +++ b/apps/constellation_app/constellation_sign_msg.c @@ -427,12 +427,9 @@ static size_t constellation_get_prefixed_msg_data( size_t prefix_len, char *prefixed_msg_data) { size_t msg_len = ctx->init.message_size; - core_scroll_page("msg", (const char *)ctx->msg_data, NULL); - core_scroll_page("prefix", prefix, NULL); char length_string[20] = ""; size_t length_string_len = sprintf(length_string, "%u\n", msg_len); - core_scroll_page("length_string", length_string, NULL); size_t total_len = prefix_len + length_string_len + msg_len; @@ -443,7 +440,6 @@ static size_t constellation_get_prefixed_msg_data( length_string, (const char *)ctx->msg_data); - core_scroll_page("prefixed_msg_data", prefixed_msg_data, NULL); return total_len; } From 08151b457a449be1812bc16d4f64fdcc75ad3247 Mon Sep 17 00:00:00 2001 From: Muzaffar Ahmad Bhat Date: Fri, 30 May 2025 11:12:12 +0530 Subject: [PATCH 75/75] chore: Version bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 5f2b6de34..86109041a 100755 --- a/version.txt +++ b/version.txt @@ -1,3 +1,3 @@ -firmware version=000:006:010:003 +firmware version=000:006:010:004 hardware version=000:001:000:000 magic number=45227A01