What changed, and why it matters
This commit is a code cleanup that removes a dedicated imToken wallet connection module and routes imToken through the existing MetaMask-style connection code. It also adds the ability to include the wallet name when generating connection data for MetaMask-compatible wallets. There is no direct evidence in the commit that this fixes a security vulnerability.
No immediate security action required. Treat as routine refactor. If reviewing for security, verify that passing user-controlled wallet names into UR generation does not introduce injection or length issues, and that the removed imtoken.rs path did not enforce any security policy that the MetaMask path now bypasses.
Security signals we found
No explicit security fix described in commit title or message
No bounds-checking, input validation, or memory-safety changes visible
Removal of duplicated code path reduces maintenance surface, but this is a hygiene change
Wallet name now propagated into crypto HD key UR generation, which is a feature/behavior change rather than a vulnerability fix
Evidence from the diff
The change deletes rust/rust_c/src/wallet/multi_coins_wallet/imtoken.rs and removes its module declaration. The imToken C entry point GuiGetImTokenData now delegates to GetMetamaskDataForAccountType(Bip44Standard), which internally calls the same UR generation path used for MetaMask. The Rust functions get_connect_metamask_ur, get_connect_metamask_ur_unlimited, and get_connect_metamask_ur_dynamic gain a new wallet_name parameter, and callers in gui_wallet.c and test_cmd.c pass GetWalletName(). The previous MetaMask path passed None for the wallet name; now it passes the user-visible wallet name. This is a functional refactor, not a clear security patch.
Changed components
rust/rust_c/src/wallet/multi_coins_wallet/imtoken.rsrust/rust_c/src/wallet/multi_coins_wallet/mod.rssrc/ui/gui_wallet/multi/web3/gui_wallet.ctest/test_cmd.cInspect captured patch +16 / −60
diff --git a/rust/rust_c/src/wallet/multi_coins_wallet/imtoken.rs b/rust/rust_c/src/wallet/multi_coins_wallet/imtoken.rs
deleted file mode 100644
index fe1b779..0000000
--- a/rust/rust_c/src/wallet/multi_coins_wallet/imtoken.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-use crate::common::types::{Ptr, PtrBytes, PtrString};
-use crate::common::ur::UREncodeResult;
-use crate::common::utils::recover_c_char;
-use crate::extract_array;
-use alloc::format;
-use alloc::string::ToString;
-use app_wallets::metamask::ETHAccountTypeApp::Bip44Standard;
-use cty::uint32_t;
-use ur_registry::crypto_hd_key::CryptoHDKey;
-use ur_registry::error::URError;
-use ur_registry::traits::RegistryItem;
-
-//only support export bip44standard eth account to imToken, rewrite this func if imToken supports other chains
-#[no_mangle]
-pub unsafe extern "C" fn get_connect_imtoken_ur(
- master_fingerprint: PtrBytes,
- master_fingerprint_length: uint32_t,
- xpub: PtrString,
- wallet_name: PtrString,
-) -> Ptr<UREncodeResult> {
- if master_fingerprint_length != 4 {
- return UREncodeResult::from(URError::UrEncodeError(format!(
- "master fingerprint length must be 4, current is {master_fingerprint_length}"
- )))
- .c_ptr();
- }
- let mfp = extract_array!(master_fingerprint, u8, master_fingerprint_length);
- let mfp = match <&[u8; 4]>::try_from(mfp) {
- Ok(mfp) => mfp,
- Err(e) => return UREncodeResult::from(URError::UrEncodeError(e.to_string())).c_ptr(),
- };
- let wallet_name = recover_c_char(wallet_name);
- let result = app_wallets::metamask::generate_standard_legacy_hd_key(
- mfp,
- &recover_c_char(xpub),
- Bip44Standard,
- Some(wallet_name),
- );
- match result.map(|v| v.try_into()) {
- Ok(v) => match v {
- Ok(data) => {
- UREncodeResult::encode(data, CryptoHDKey::get_registry_type().get_type(), 240)
- .c_ptr()
- }
- Err(e) => UREncodeResult::from(e).c_ptr(),
- },
- Err(e) => UREncodeResult::from(e).c_ptr(),
- }
-}
diff --git a/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs b/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs
index 6b6ef4c..cc23f91 100644
--- a/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs
+++ b/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs
@@ -1,7 +1,6 @@
pub mod arconnect;
pub mod backpack;
pub mod bitget;
-mod imtoken;
pub mod keplr;
pub mod keystone_connect;
pub mod okx;
@@ -65,6 +64,7 @@ pub unsafe extern "C" fn get_connect_metamask_ur_dynamic(
master_fingerprint_length: uint32_t,
account_type: ETHAccountType,
public_keys: PtrT<CSliceFFI<ExtendedPublicKey>>,
+ wallet_name: PtrString,
fragment_max_length_default: usize,
fragment_max_length_other: usize,
) -> *mut UREncodeResult {
@@ -79,6 +79,11 @@ pub unsafe extern "C" fn get_connect_metamask_ur_dynamic(
Ok(mfp) => mfp,
Err(e) => return UREncodeResult::from(URError::UrEncodeError(e.to_string())).c_ptr(),
};
+ let wallet_name = if wallet_name.is_null() {
+ None
+ } else {
+ Some(recover_c_char(wallet_name))
+ };
let keys = recover_c_array(public_keys);
match account_type {
@@ -118,7 +123,7 @@ pub unsafe extern "C" fn get_connect_metamask_ur_dynamic(
mfp,
&recover_c_char(k.xpub),
account_type.into(),
- None,
+ wallet_name,
);
match result.map(|v| v.try_into()) {
Ok(v) => match v {
@@ -145,12 +150,14 @@ pub unsafe extern "C" fn get_connect_metamask_ur_unlimited(
master_fingerprint_length: uint32_t,
account_type: ETHAccountType,
public_keys: PtrT<CSliceFFI<ExtendedPublicKey>>,
+ wallet_name: PtrString,
) -> *mut UREncodeResult {
get_connect_metamask_ur_dynamic(
master_fingerprint,
master_fingerprint_length,
account_type,
public_keys,
+ wallet_name,
FRAGMENT_UNLIMITED_LENGTH,
FRAGMENT_UNLIMITED_LENGTH,
)
@@ -162,12 +169,14 @@ pub unsafe extern "C" fn get_connect_metamask_ur(
master_fingerprint_length: uint32_t,
account_type: ETHAccountType,
public_keys: PtrT<CSliceFFI<ExtendedPublicKey>>,
+ wallet_name: PtrString,
) -> *mut UREncodeResult {
get_connect_metamask_ur_dynamic(
master_fingerprint,
master_fingerprint_length,
account_type,
public_keys,
+ wallet_name,
FRAGMENT_MAX_LENGTH_DEFAULT,
240,
)
diff --git a/src/ui/gui_wallet/multi/web3/gui_wallet.c b/src/ui/gui_wallet/multi/web3/gui_wallet.c
index ed1da35..a43e0d8 100644
--- a/src/ui/gui_wallet/multi/web3/gui_wallet.c
+++ b/src/ui/gui_wallet/multi/web3/gui_wallet.c
@@ -150,11 +150,11 @@ UREncodeResult *GuiGetSparrowWalletBtcData(void)
return urEncode;
}
-typedef UREncodeResult *MetamaskUrGetter(PtrBytes master_fingerprint, uint32_t master_fingerprint_length, enum ETHAccountType account_type, PtrT_CSliceFFI_ExtendedPublicKey public_keys);
+typedef UREncodeResult *MetamaskUrGetter(PtrBytes master_fingerprint, uint32_t master_fingerprint_length, enum ETHAccountType account_type, PtrT_CSliceFFI_ExtendedPublicKey public_keys, PtrString wallet_name);
static UREncodeResult *get_unlimited_connect_metamask_ur(PtrBytes master_fingerprint, uint32_t master_fingerprint_length, enum ETHAccountType account_type, PtrT_CSliceFFI_ExtendedPublicKey public_keys)
{
- return get_connect_metamask_ur_unlimited(master_fingerprint, master_fingerprint_length, account_type, public_keys);
+ return get_connect_metamask_ur_unlimited(master_fingerprint, master_fingerprint_length, account_type, public_keys, GetWalletName());
}
static UREncodeResult *BasicGetMetamaskDataForAccountType(ETHAccountType accountType, MetamaskUrGetter func)
@@ -196,7 +196,7 @@ static UREncodeResult *BasicGetMetamaskDataForAccountType(ETHAccountType account
return NULL;
}
- UREncodeResult *urEncode = func(mfp, sizeof(mfp), accountType, public_keys);
+ UREncodeResult *urEncode = func(mfp, sizeof(mfp), accountType, public_keys, GetWalletName());
if (urEncode == NULL) {
SRAM_FREE(public_keys);
return NULL;
@@ -224,11 +224,7 @@ UREncodeResult *GuiGetMetamaskData(void)
UREncodeResult *GuiGetImTokenData(void)
{
- uint8_t mfp[4] = {0};
- GetMasterFingerPrint(mfp);
- UREncodeResult *urEncode = get_connect_imtoken_ur(mfp, sizeof(mfp), GetCurrentAccountPublicKey(XPUB_TYPE_ETH_BIP44_STANDARD), GetWalletName());
- CHECK_CHAIN_PRINT(urEncode);
- return urEncode;
+ return GetMetamaskDataForAccountType(Bip44Standard);
}
UREncodeResult *GuiGetCoreWalletData(void)
diff --git a/test/test_cmd.c b/test/test_cmd.c
index be37c29..d1b3c4b 100644
--- a/test/test_cmd.c
+++ b/test/test_cmd.c
@@ -1905,7 +1905,7 @@ static void RustGetConnectMetaMaskUR(int argc, char *argv[])
PtrT_CSliceFFI_ExtendedPublicKey public_keys = SRAM_MALLOC(sizeof(CSliceFFI_ExtendedPublicKey));
public_keys->size = 10;
public_keys->data = keys;
- PtrT_UREncodeResult ur = get_connect_metamask_ur(mfp, sizeof(mfp), LedgerLive, public_keys);
+ PtrT_UREncodeResult ur = get_connect_metamask_ur(mfp, sizeof(mfp), LedgerLive, public_keys, GetWalletName());
printf("encode ur\r\n");
printf("is_multi_part is %d\r\n", ur->is_multi_part);
printf("data is %s\r\n", ur->data);
Why this scored 11/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.