What changed, and why it matters
This commit is a code review and cleanup of the Cosmos cryptocurrency support in the Keystone 3 hardware wallet firmware. It fixes several small but real issues: it corrects a buffer-size mismatch when copying passwords/passphrases into memory, avoids unnecessary cloning of transaction data, adds zeroing of the seed buffer after signing, and fixes memory leaks and repeated JSON parsing in the Cosmos UI code. There is no clear evidence of an exploitable remote attack, but the changes reduce the chance of memory corruption and secret leakage.
Treat as a hardening/maintenance patch. Review the corrected `strcpy_s` sizes and the new `seed.zeroize()` path for completeness (ensure no early returns skip zeroization). Verify that `GetCosmosParsedDetailRoot` cache invalidation covers all places where `tx->detail` may be freed or replaced. No urgent user action is indicated absent a vendor security advisory.
Security signals we found
Buffer copy size corrected in secret cache (password/passphrase/new password)
Seed buffer zeroized after Cosmos/Evmos signing
Removed redundant heap clones in transaction parsing
Added null checks and JSON parse caching to reduce use-after-free / memory-leak surface in UI
Fixed unconditional simulator-only memory free path
Global fixed-size address buffer removed
Evidence from the diff
The patch is a defensive review of Cosmos/Evmos signing and display paths. Key changes: (1) secret_cache.c now allocates and copies passwords/passphrases using the actual measured length instead of the max macro, fixing a potential strcpy_s destination-size mismatch. (2) rust_c/src/cosmos/mod.rs switches cosmos_sign_tx to a mutable seed slice and calls zeroize() after signing, reducing seed material lifetime. (3) rust/apps/cosmos replaces &Vec<u8> with &[u8] and removes redundant .clone() calls in amino/direct transaction parsing. (4) gui_cosmos.c introduces a cached parsed JSON root (GetCosmosParsedDetailRoot) to avoid repeated cJSON_Parse/cJSON_Delete cycles, adds null checks, removes a fixed global address buffer, and uses a stack buffer for chain-id lookup. It also moves ClearSecretCache() outside the success path so it always runs. The commit message is only “review cosmos” and no CVE or vendor security advisory is supplied.
Changed components
rust/apps/cosmos/src/lib.rsrust/apps/cosmos/src/transaction/mod.rsrust/rust_c/src/cosmos/mod.rssrc/crypto/secret_cache.csrc/ui/gui_chain/multi/web3/gui_cosmos.cInspect captured patch +133 / −98
diff --git a/rust/apps/cosmos/src/lib.rs b/rust/apps/cosmos/src/lib.rs
index 99f9926..51cbef6 100644
--- a/rust/apps/cosmos/src/lib.rs
+++ b/rust/apps/cosmos/src/lib.rs
@@ -10,7 +10,6 @@ extern crate core;
extern crate std;
use alloc::string::{String, ToString};
-use alloc::vec::Vec;
use crate::errors::{CosmosError, Result};
use crate::transaction::structs::{ParsedCosmosTx, SignMode};
@@ -30,7 +29,9 @@ fn generate_evmos_address(key: PublicKey, prefix: &str) -> Result<String> {
let keccak: [u8; 32] = keccak256(&key.serialize_uncompressed()[1..]);
let keccak160: [u8; 20] = keccak[keccak.len() - 20..keccak.len()]
.try_into()
- .map_err(|_e| CosmosError::InvalidAddressError("keccak160 failed failed".to_string()))?;
+ .map_err(|_e| {
+ CosmosError::InvalidAddressError("keccak160 conversion failed".to_string())
+ })?;
let hrp = Hrp::parse_unchecked(prefix);
let address = bech32::encode::<Bech32>(hrp, &keccak160)?;
Ok(address)
@@ -50,35 +51,25 @@ fn generate_address(key: PublicKey, prefix: &str) -> Result<String> {
}
}
-// pub fn parse_raw_tx(raw_tx: &Vec<u8>) -> Result<String> {
-// SignDoc::parse(raw_tx).map(|doc| {
-// serde_json::to_string(&doc).map_err(|err| CosmosError::ParseTxError(err.to_string()))
-// })?
-// }
-
-pub fn parse(
- raw_tx: &Vec<u8>,
- data_type: transaction::structs::DataType,
-) -> Result<ParsedCosmosTx> {
+pub fn parse(raw_tx: &[u8], data_type: transaction::structs::DataType) -> Result<ParsedCosmosTx> {
ParsedCosmosTx::build(raw_tx, data_type)
}
pub fn sign_tx(
- message: Vec<u8>,
+ message: &[u8],
path: &String,
sign_mode: SignMode,
seed: &[u8],
) -> Result<[u8; 64]> {
let hash = match sign_mode {
- SignMode::COSMOS => sha256_digest(message.as_slice()),
- SignMode::EVM => keccak256(message.as_slice()).to_vec(),
+ SignMode::COSMOS => sha256_digest(message),
+ SignMode::EVM => keccak256(message).to_vec(),
};
- if let Ok(message) = Message::from_slice(&hash) {
- let (_, signature) = keystore::algorithms::secp256k1::sign_message_by_seed(
- seed, path, &message,
- )
- .map_err(|e| CosmosError::KeystoreError(format!("sign failed {:?}", e.to_string())))?;
+ if let Ok(message) = Message::from_slice(hash.as_slice()) {
+ let (_, signature) =
+ keystore::algorithms::secp256k1::sign_message_by_seed(seed, path, &message)
+ .map_err(|e| CosmosError::KeystoreError(format!("sign failed {e}")))?;
return Ok(signature);
}
Err(CosmosError::SignFailure("invalid message".to_string()))
@@ -91,7 +82,7 @@ pub fn derive_address(
prefix: &str,
) -> Result<String> {
let root_path = if !root_path.ends_with('/') {
- root_path.to_string() + "/"
+ format!("{root_path}/")
} else {
root_path.to_string()
};
diff --git a/rust/apps/cosmos/src/transaction/mod.rs b/rust/apps/cosmos/src/transaction/mod.rs
index fcff912..005b953 100644
--- a/rust/apps/cosmos/src/transaction/mod.rs
+++ b/rust/apps/cosmos/src/transaction/mod.rs
@@ -19,7 +19,7 @@ pub mod structs;
mod utils;
impl ParsedCosmosTx {
- pub fn build(data: &Vec<u8>, data_type: DataType) -> Result<Self> {
+ pub fn build(data: &[u8], data_type: DataType) -> Result<Self> {
match data_type {
DataType::Amino => Self::build_from_amino(data),
DataType::Direct => Self::build_from_direct(data),
@@ -45,7 +45,7 @@ impl ParsedCosmosTx {
// _ => CosmosTxDisplayType::Unknown,
}
}
- fn build_overview_from_amino(data: Value) -> Result<CosmosTxOverview> {
+ fn build_overview_from_amino(data: &Value) -> Result<CosmosTxOverview> {
let chain_id = data["chain_id"].as_str().unwrap_or("");
let kind = CosmosTxOverview::from_value(&data["msgs"])?;
let common = CommonOverview {
@@ -58,7 +58,7 @@ impl ParsedCosmosTx {
})
}
- fn build_detail_from_amino(data: Value) -> Result<String> {
+ fn build_detail_from_amino(data: &Value) -> Result<String> {
let chain_id = data["chain_id"].as_str().unwrap_or("");
let common = CommonDetail {
network: get_network_by_chain_id(chain_id)?,
@@ -78,24 +78,23 @@ impl ParsedCosmosTx {
Ok(detail)
}
- fn build_from_amino(data: &Vec<u8>) -> Result<Self> {
- let v: Value = from_slice(data.as_slice())?;
- let overview = Self::build_overview_from_amino(v.clone())?;
+ fn build_from_value(v: &Value) -> Result<Self> {
Ok(Self {
- overview,
- detail: Self::build_detail_from_amino(v.clone())?,
+ overview: Self::build_overview_from_amino(v)?,
+ detail: Self::build_detail_from_amino(v)?,
})
}
- fn build_from_direct(data: &Vec<u8>) -> Result<Self> {
+ fn build_from_amino(data: &[u8]) -> Result<Self> {
+ let v: Value = from_slice(data)?;
+ Self::build_from_value(&v)
+ }
+
+ fn build_from_direct(data: &[u8]) -> Result<Self> {
let sign_doc = SignDoc::parse(data)?;
let doc_str = serde_json::to_string(&sign_doc)?;
let v: Value = from_str(doc_str.as_str())?;
- let overview = Self::build_overview_from_amino(v.clone())?;
- Ok(Self {
- overview,
- detail: Self::build_detail_from_amino(v.clone())?,
- })
+ Self::build_from_value(&v)
}
}
@@ -112,8 +111,7 @@ mod tests {
fn test_parse_cosmos_send_amino_json() {
//{"account_number": String("1674671"), "chain_id": String("cosmoshub-4"), "fee": Object {"amount": Array [Object {"amount": String("2583"), "denom": String("uatom")}], "gas": String("103301")}, "memo": String(""), "msgs": Array [Object {"type": String("cosmos-sdk/MsgSend"), "value": Object {"amount": Array [Object {"amount": String("12000"), "denom": String("uatom")}], "from_address": String("cosmos17u02f80vkafne9la4wypdx3kxxxxwm6f2qtcj2"), "to_address": String("cosmos1kwml7yt4em4en7guy6het2q3308u73dff983s3")}}], "sequence": String("2")}
let raw_tx = "7B226163636F756E745F6E756D626572223A2231363734363731222C22636861696E5F6964223A22636F736D6F736875622D34222C22666565223A7B22616D6F756E74223A5B7B22616D6F756E74223A2232353833222C2264656E6F6D223A227561746F6D227D5D2C22676173223A22313033333031227D2C226D656D6F223A22222C226D736773223A5B7B2274797065223A22636F736D6F732D73646B2F4D736753656E64222C2276616C7565223A7B22616D6F756E74223A5B7B22616D6F756E74223A223132303030222C2264656E6F6D223A227561746F6D227D5D2C2266726F6D5F61646472657373223A22636F736D6F733137753032663830766B61666E65396C61347779706478336B78787878776D3666327174636A32222C22746F5F61646472657373223A22636F736D6F73316B776D6C37797434656D34656E37677579366865743271333330387537336466663938337333227D7D5D2C2273657175656E6365223A2232227D";
- let result =
- ParsedCosmosTx::build(&hex::decode(raw_tx).unwrap().to_vec(), DataType::Amino).unwrap();
+ let result = ParsedCosmosTx::build(&hex::decode(raw_tx).unwrap(), DataType::Amino).unwrap();
let overview = result.overview;
assert_eq!("Cosmos Hub", overview.common.network);
match overview.kind[0].clone() {
@@ -204,8 +202,7 @@ mod tests {
// Object {"account_number": Number(2318430), "Chain ID": String("evmos_9000-4"), "Fee": Object {"amount": Array [Object {"amount": String("8750000000000000"), "denom": String("atevmos")}], "gas": Number(350000), "granter": String(""), "payer": String("")}, "memo": String(""), "msgs": Array [Object {"type": String("/cosmos.staking.v1beta1.MsgDelegate"), "Value": Object {"amount": Object {"amount": String("10000000000000000"), "denom": String("atevmos")}, "delegator_address": String("evmos1tqsdz785sqjnlggee0lwxjwfk6dl36ae2uf9er"), "validator_address": String("evmosvaloper10t6kyy4jncvnevmgq6q2ntcy90gse3yxa7x2p4")}}]}
let raw_tx = "0AAC010AA9010A232F636F736D6F732E7374616B696E672E763162657461312E4D736744656C65676174651281010A2C65766D6F7331747173647A37383573716A6E6C67676565306C77786A77666B36646C33366165327566396572123365766D6F7376616C6F706572313074366B7979346A6E63766E65766D67713671326E74637939306773653379786137783270341A1C0A07617465766D6F7312113130303030303030303030303030303030127C0A570A4F0A282F65746865726D696E742E63727970746F2E76312E657468736563703235366B312E5075624B657912230A21039F4E693730F116E7AB01DAC46B94AD4FCABC3CA7D91A6B121CC26782A8F2B8B212040A02080112210A1B0A07617465766D6F7312103837353030303030303030303030303010B0AE151A0C65766D6F735F393030302D3420DEC08D01";
let result =
- ParsedCosmosTx::build(&hex::decode(raw_tx).unwrap().to_vec(), DataType::Direct)
- .unwrap();
+ ParsedCosmosTx::build(&hex::decode(raw_tx).unwrap(), DataType::Direct).unwrap();
let overview = result.overview;
assert_eq!("Evmos Testnet", overview.common.network);
assert_eq!(CosmosTxDisplayType::Delegate, overview.display_type);
diff --git a/rust/rust_c/src/cosmos/mod.rs b/rust/rust_c/src/cosmos/mod.rs
index 9cf0df3..fbf06cf 100644
--- a/rust/rust_c/src/cosmos/mod.rs
+++ b/rust/rust_c/src/cosmos/mod.rs
@@ -5,7 +5,7 @@ use crate::common::structs::{SimpleResponse, TransactionCheckResult, Transaction
use crate::common::types::{PtrBytes, PtrString, PtrT, PtrUR};
use crate::common::ur::{QRCodeType, UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT};
use crate::common::utils::{convert_c_char, recover_c_char};
-use crate::extract_array;
+use crate::{extract_array, extract_array_mut};
use crate::extract_ptr_with_type;
use alloc::format;
use alloc::string::{String, ToString};
@@ -21,6 +21,7 @@ use ur_registry::cosmos::cosmos_signature::CosmosSignature;
use ur_registry::cosmos::evm_sign_request::{EvmSignRequest, SignDataType};
use ur_registry::cosmos::evm_signature::EvmSignature;
use ur_registry::traits::RegistryItem;
+use zeroize::Zeroize;
fn get_public_key(seed: &[u8], path: &String) -> Result<Vec<u8>, CosmosError> {
let path = normalize_path(path);
@@ -49,7 +50,7 @@ unsafe fn build_sign_result(
CosmosError::SignFailure("invalid derivation path".to_string()),
)?;
let signature = app_cosmos::sign_tx(
- sign_request.get_sign_data().to_vec(),
+ sign_request.get_sign_data().as_slice(),
&path,
SignMode::COSMOS,
seed,
@@ -70,7 +71,7 @@ unsafe fn build_sign_result(
"invalid derivation path".to_string(),
))?;
let signature = app_cosmos::sign_tx(
- sign_request.get_sign_data().to_vec(),
+ sign_request.get_sign_data().as_slice(),
&path,
SignMode::EVM,
seed,
@@ -157,7 +158,7 @@ pub unsafe extern "C" fn cosmos_sign_tx(
seed: PtrBytes,
seed_len: u32,
) -> PtrT<UREncodeResult> {
- let seed = extract_array!(seed, u8, seed_len as usize);
+ let mut seed: &mut [u8] = extract_array_mut!(seed, u8, seed_len as usize);
let ur_tag = match ur_type {
QRCodeType::CosmosSignRequest => CosmosSignature::get_registry_type().get_type(),
QRCodeType::EvmSignRequest => EvmSignature::get_registry_type().get_type(),
@@ -168,7 +169,7 @@ pub unsafe extern "C" fn cosmos_sign_tx(
.c_ptr()
}
};
- build_sign_result(ptr, ur_type, seed)
+ let result = build_sign_result(ptr, ur_type, seed)
.map(|v| match v {
Either::Left(sig) => sig.try_into(),
Either::Right(sig) => sig.try_into(),
@@ -183,7 +184,9 @@ pub unsafe extern "C" fn cosmos_sign_tx(
},
)
},
- )
+ );
+ seed.zeroize();
+ result
}
#[no_mangle]
diff --git a/src/crypto/secret_cache.c b/src/crypto/secret_cache.c
index 30e39cc..fccd0c0 100644
--- a/src/crypto/secret_cache.c
+++ b/src/crypto/secret_cache.c
@@ -63,8 +63,9 @@ void SecretCacheSetPassword(char *password)
if (g_passwordCache) {
SRAM_FREE(g_passwordCache);
}
- g_passwordCache = SRAM_MALLOC(strnlen_s(password, PASSWORD_MAX_LEN) + 1);
- strcpy_s(g_passwordCache, PASSWORD_MAX_LEN, password);
+ size_t len = strnlen_s(password, PASSWORD_MAX_LEN) + 1;
+ g_passwordCache = SRAM_MALLOC(len);
+ strcpy_s(g_passwordCache, len, password);
}
char *SecretCacheGetPassword(void)
@@ -77,8 +78,9 @@ void SecretCacheSetPassphrase(const char *passPhrase)
if (g_passphraseCache) {
SRAM_FREE(g_passphraseCache);
}
- g_passphraseCache = SRAM_MALLOC(strnlen_s(passPhrase, PASSPHRASE_MAX_LEN) + 1);
- strcpy_s(g_passphraseCache, PASSPHRASE_MAX_LEN, passPhrase);
+ size_t len = strnlen_s(passPhrase, PASSPHRASE_MAX_LEN) + 1;
+ g_passphraseCache = SRAM_MALLOC(len);
+ strcpy_s(g_passphraseCache, len, passPhrase);
}
char *SecretCacheGetPassphrase(void)
@@ -91,8 +93,9 @@ void SecretCacheSetNewPassword(char *password)
if (g_newPasswordCache) {
SRAM_FREE(g_newPasswordCache);
}
- g_newPasswordCache = SRAM_MALLOC(strnlen_s(password, PASSWORD_MAX_LEN) + 1);
- strcpy_s(g_newPasswordCache, PASSWORD_MAX_LEN, password);
+ size_t len = strnlen_s(password, PASSWORD_MAX_LEN) + 1;
+ g_passwordCache = SRAM_MALLOC(len);
+ strcpy_s(g_newPasswordCache, len, password);
}
char *SecretCacheGetNewPassword(void)
diff --git a/src/ui/gui_chain/multi/web3/gui_cosmos.c b/src/ui/gui_chain/multi/web3/gui_cosmos.c
index 5e828fd..160be9a 100644
--- a/src/ui/gui_chain/multi/web3/gui_cosmos.c
+++ b/src/ui/gui_chain/multi/web3/gui_cosmos.c
@@ -8,14 +8,15 @@
#include "user_memory.h"
#include "account_manager.h"
#include "gui_chain.h"
-#define MAX_COSMOS_ADDR_LEN 61
static bool g_isMulti = false;
static URParseResult *g_urResult = NULL;
static URParseMultiResult *g_urMultiResult = NULL;
static void *g_parseResult = NULL;
static int8_t g_cosmosListIndex = -1;
-static char g_cosmosAddr[MAX_COSMOS_ADDR_LEN];
+static const char *g_cosmosLastDetailPtr = NULL;
+static cJSON *g_cosmosLastRoot = NULL;
+static cJSON *g_cosmosLastCommon = NULL;
static const CosmosChain_t g_cosmosChains[COSMOS_CHAINS_LEN] = {
{CHAIN_BABYLON, HOME_WALLET_CARD_BABYLON, 118, "bbn", XPUB_TYPE_COSMOS, "baby_3535-1"},
{CHAIN_NEUTARO, HOME_WALLET_CARD_NEUTARO, 118, "neutaro", XPUB_TYPE_COSMOS, "Neutaro-1"},
@@ -55,6 +56,18 @@ static const CosmosChain_t g_cosmosChains[COSMOS_CHAINS_LEN] = {
{CHAIN_LUNC, HOME_WALLET_CARD_LUNC, 330, "terra", XPUB_TYPE_TERRA, "columbus-5"}
};
+static void ClearCosmosDetailCache(void);
+
+static inline void* GetCosmosUrData(void)
+{
+ return g_isMulti ? g_urMultiResult->data : g_urResult->data;
+}
+
+static inline QRCodeType GetCosmosUrType(void)
+{
+ return g_isMulti ? g_urMultiResult->ur_type : g_urResult->ur_type;
+}
+
char *GetCosmosChainAddressByCoinTypeAndIndex(uint8_t chainType, uint32_t address_index)
{
char *xPub;
@@ -67,17 +80,6 @@ char *GetCosmosChainAddressByCoinTypeAndIndex(uint8_t chainType, uint32_t addre
return (char *) cosmos_get_address(hdPath, xPub, rootPath, (char*)chain->prefix);
}
-char *GetKeplrConnectionDisplayAddressByIndex(uint32_t index)
-{
- SimpleResponse_c_char *result;
- result = (SimpleResponse_c_char *) GetCosmosChainAddressByCoinTypeAndIndex(CHAIN_ATOM, index);
- if (result->error_code == 0) {
- snprintf_s(g_cosmosAddr, MAX_COSMOS_ADDR_LEN, "%s", result->data);
- }
- free_simple_response_c_char(result);
- return g_cosmosAddr;
-}
-
const CosmosChain_t *GuiGetCosmosChain(uint8_t index)
{
for (int i = 0; i < COSMOS_CHAINS_LEN; i++) {
@@ -137,11 +139,9 @@ void *GuiGetCosmosData(void)
{
CHECK_FREE_PARSE_RESULT(g_parseResult);
uint8_t mfp[4];
- void *data = g_isMulti ? g_urMultiResult->data : g_urResult->data;
GetMasterFingerPrint(mfp);
do {
- QRCodeType urType = g_isMulti ? g_urMultiResult->ur_type : g_urResult->ur_type;
- PtrT_TransactionParseResult_DisplayCosmosTx parseResult = cosmos_parse_tx(data, urType);
+ PtrT_TransactionParseResult_DisplayCosmosTx parseResult = cosmos_parse_tx(GetCosmosUrData(), GetCosmosUrType());
CHECK_CHAIN_BREAK(parseResult);
g_parseResult = (void *)parseResult;
} while (0);
@@ -151,19 +151,16 @@ void *GuiGetCosmosData(void)
PtrT_TransactionCheckResult GuiGetCosmosCheckResult(void)
{
uint8_t mfp[4];
- void *data = g_isMulti ? g_urMultiResult->data : g_urResult->data;
GetMasterFingerPrint(mfp);
- QRCodeType urType = g_isMulti ? g_urMultiResult->ur_type : g_urResult->ur_type;
- return cosmos_check_tx(data, urType, mfp, sizeof(mfp));
+ return cosmos_check_tx(GetCosmosUrData(), GetCosmosUrType(), mfp, sizeof(mfp));
}
void FreeCosmosMemory(void)
{
-#ifndef COMPILE_SIMULATOR
CHECK_FREE_UR_RESULT(g_urResult, false);
CHECK_FREE_UR_RESULT(g_urMultiResult, true);
CHECK_FREE_PARSE_RESULT(g_parseResult);
-#endif
+ ClearCosmosDetailCache();
}
void GuiGetCosmosTmpType(void *indata, void *param, uint32_t maxLen)
@@ -187,6 +184,33 @@ bool IsCosmosMsg(ViewType viewType)
return strcmp(data->overview->display_type, GuiGetCosmosTxTypeName(COSMOS_MESSAGE)) == 0;
}
+static void ClearCosmosDetailCache(void)
+{
+ if (g_cosmosLastRoot != NULL) {
+ cJSON_Delete(g_cosmosLastRoot);
+ g_cosmosLastRoot = NULL;
+ }
+ g_cosmosLastCommon = NULL;
+ g_cosmosLastDetailPtr = NULL;
+}
+
+static cJSON *GetCosmosParsedDetailRoot(DisplayCosmosTx *tx)
+{
+ if (tx == NULL || tx->detail == NULL) {
+ return NULL;
+ }
+ if (g_cosmosLastDetailPtr == tx->detail && g_cosmosLastRoot != NULL) {
+ return g_cosmosLastRoot;
+ }
+ ClearCosmosDetailCache();
+ g_cosmosLastRoot = cJSON_Parse((const char *)tx->detail);
+ g_cosmosLastDetailPtr = tx->detail;
+ if (g_cosmosLastRoot != NULL) {
+ g_cosmosLastCommon = cJSON_GetObjectItem(g_cosmosLastRoot, "common");
+ }
+ return g_cosmosLastRoot;
+}
+
void GetCosmosValue(void *indata, void *param, uint32_t maxLen)
{
DisplayCosmosTx *tx = (DisplayCosmosTx *)param;
@@ -302,8 +326,12 @@ void GetCosmosAddress2Label(void *indata, void *param, uint32_t maxLen)
void GetCosmosDetailCommon(void *indata, void *param, const char* key, uint32_t maxLen)
{
DisplayCosmosTx *tx = (DisplayCosmosTx *)param;
- cJSON* root = cJSON_Parse((const char *)tx->detail);
- cJSON* common = cJSON_GetObjectItem(root, "common");
+ cJSON* root = GetCosmosParsedDetailRoot(tx);
+ if (root == NULL) {
+ strcpy_s((char *)indata, maxLen, "");
+ return;
+ }
+ cJSON* common = g_cosmosLastCommon;
if (common == NULL) {
strcpy_s((char *)indata, maxLen, "");
return;
@@ -344,7 +372,11 @@ void GetCosmosChainId(void *indata, void *param, uint32_t maxLen)
static void GetCosmosDetailNthKind(void *indata, void *param, int n, const char* key, uint32_t maxLen)
{
DisplayCosmosTx *tx = (DisplayCosmosTx *)param;
- cJSON* root = cJSON_Parse((const char *)tx->detail);
+ cJSON* root = GetCosmosParsedDetailRoot(tx);
+ if (root == NULL) {
+ strcpy_s((char *)indata, maxLen, "");
+ return;
+ }
cJSON* kind = cJSON_GetObjectItem(root, "kind");
cJSON* item = cJSON_GetArrayItem(kind, n);
cJSON* value = cJSON_GetObjectItem(item, key);
@@ -365,7 +397,12 @@ void GetCosmosOldValidator(void *indata, void *param, uint32_t maxLen)
void GetCosmosMsgLen(uint8_t *len, void *param)
{
DisplayCosmosTx *tx = (DisplayCosmosTx *)param;
- cJSON* root = cJSON_Parse((const char *)tx->detail);
+ cJSON* root = GetCosmosParsedDetailRoot(tx);
+ if (root == NULL) {
+ *len = 0;
+ g_cosmosListIndex = -1;
+ return;
+ }
cJSON* kind = cJSON_GetObjectItem(root, "kind");
*len = (uint8_t)cJSON_GetArraySize(kind);
g_cosmosListIndex = -1;
@@ -391,8 +428,12 @@ void GetCosmosTextOfKind(void *indata, void *param, uint32_t maxLen)
void GetCosmosDetailItemValue(void *indata, void *param, uint32_t maxLen)
{
DisplayCosmosTx *tx = (DisplayCosmosTx *)param;
- cJSON* detail = cJSON_Parse((const char *)tx->detail);
- cJSON* value = cJSON_GetObjectItem(detail, indata);
+ cJSON* root = GetCosmosParsedDetailRoot(tx);
+ if (root == NULL) {
+ strcpy_s((char *)indata, maxLen, "");
+ return;
+ }
+ cJSON* value = cJSON_GetObjectItem(root, indata);
if (value == NULL) {
strcpy_s((char *)indata, maxLen, "");
} else {
@@ -565,26 +606,25 @@ uint8_t GuiGetCosmosTxChain(void)
if (parseResult == NULL) {
return CHAIN_ATOM;
}
- char* chain_id = SRAM_MALLOC(BUFFER_SIZE_64);
+ char chain_id[BUFFER_SIZE_64] = {0};
if (strcmp(parseResult->data->overview->display_type, GuiGetCosmosTxTypeName(COSMOS_MESSAGE)) == 0 || strcmp(parseResult->data->overview->display_type, GuiGetCosmosTxTypeName(COSMOS_TX_UNKNOWN)) == 0) {
- cJSON* detail = cJSON_Parse(parseResult->data->detail);
- cJSON* value = cJSON_GetObjectItem(detail, "Chain ID");
+ cJSON* root = GetCosmosParsedDetailRoot(parseResult->data);
+ cJSON* value = root == NULL ? NULL : cJSON_GetObjectItem(root, "Chain ID");
+ if (value == NULL) {
+ return CHAIN_ATOM;
+ }
snprintf_s(chain_id, BUFFER_SIZE_64, "%s", value->valuestring);
} else {
GetCosmosDetailCommon(chain_id, parseResult->data, "Chain ID", BUFFER_SIZE_64);
}
- printf("chain_id: %s\n", chain_id);
- if (chain_id != NULL) {
- for (uint8_t i = 0; i < COSMOS_CHAINS_LEN; i++) {
- if (strcmp(chain_id, g_cosmosChains[i].chainId) == 0) {
- return g_cosmosChains[i].index;
- }
- }
- if (strcmp(chain_id, "evmos_9000-4") == 0) {
- return CHAIN_EVMOS;
+ for (uint8_t i = 0; i < COSMOS_CHAINS_LEN; i++) {
+ if (strcmp(chain_id, g_cosmosChains[i].chainId) == 0) {
+ return g_cosmosChains[i].index;
}
}
- SRAM_FREE(chain_id);
+ if (strcmp(chain_id, "evmos_9000-4") == 0) {
+ return CHAIN_EVMOS;
+ }
return CHAIN_ATOM;
}
@@ -593,16 +633,17 @@ UREncodeResult *GuiGetCosmosSignQrCodeData(void)
bool enable = IsPreviousLockScreenEnable();
SetLockScreen(false);
UREncodeResult *encodeResult;
- void *data = g_isMulti ? g_urMultiResult->data : g_urResult->data;
- QRCodeType urType = g_isMulti ? g_urMultiResult->ur_type : g_urResult->ur_type;
+ uint8_t seed[SEED_LEN];
do {
- uint8_t seed[64];
- int len = GetMnemonicType() == MNEMONIC_TYPE_BIP39 ? sizeof(seed) : GetCurrentAccountEntropyLen();
- GetAccountSeed(GetCurrentAccountIndex(), seed, SecretCacheGetPassword());
- encodeResult = cosmos_sign_tx(data, urType, seed, len);
- ClearSecretCache();
+ int ret = GetAccountSeed(GetCurrentAccountIndex(), seed, SecretCacheGetPassword());
+ if (ret != SUCCESS_CODE) {
+ break;
+ }
+ encodeResult = cosmos_sign_tx(GetCosmosUrData(), GetCosmosUrType(), seed, GetCurrentAccountSeedLen());
CHECK_CHAIN_BREAK(encodeResult);
} while (0);
+ memset_s(seed, sizeof(seed), 0, sizeof(seed));
+ ClearSecretCache();
SetLockScreen(enable);
return encodeResult;
}
Why this scored 41/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.