What changed, and why it matters
This commit removes a function that filled public key info for all cryptocurrency chains and adds a null-password check in the RSA key-reading path. The stated goal is to fix a crash. The crash likely happened because RSA key generation/reading ran while the password cache was empty, causing GetAccountSeed to dereference a null password. Removing the broad chain-info filler may also prevent crashes from partially initialized state during wallet setup or account switching.
Treat as a stability/defensive fix. Review whether other callers of GetAccountSeed or SecretCacheGetPassword also need null guards, and confirm FillPublicInfoForAllChains is fully replaced by safer callers. If the crash was externally reachable, consider a security advisory; otherwise monitor for follow-up commits.
Security signals we found
Null-pointer dereference crash fixed by guarding SecretCacheGetPassword() before use
Removal of broad public-info derivation loop that may have exercised RSA derivation at unsafe times
Crash in cryptographic key derivation path on hardware wallet firmware
No explicit bounds or memory safety changes; change is defensive null check and code removal
Evidence from the diff
The patch deletes FillPublicInfoForAllChains(), which iterated g_chainTable, called DeriveChainXpub for every non-TON chain, and stored results in g_accountPublicInfo. It also inserts a NULL check for SecretCacheGetPassword() inside FlashReadRsaPrimes() before calling GetAccountSeed(…, SecretCacheGetPassword()). The RSA path previously could pass a NULL password to GetAccountSeed, which probably dereferences it and crashes. The removed function is no longer referenced in the shown diff; its deletion may be cleanup or a way to avoid invoking derivation before the password cache is populated.
Changed components
src/crypto/account_public_info.csrc/crypto/rsa.cRSA key loading/derivationAccount public key derivation (all-chain filler)Inspect captured patch +4 / −38
diff --git a/src/crypto/account_public_info.c b/src/crypto/account_public_info.c
index 050b56d..76d92d2 100644
--- a/src/crypto/account_public_info.c
+++ b/src/crypto/account_public_info.c
@@ -579,44 +579,6 @@ static int32_t WritePublicJsonAndHash(uint8_t accountIndex, uint32_t addr, const
return SUCCESS_CODE;
}
-// enumerate and fill all non-TON chains
-static int32_t FillPublicInfoForAllChains(const uint8_t *seed, int seedLen, const char *password,
- const char *icarusMasterKey, const char *ledgerBitbox02Key,
- bool isSlip39)
-{
- int32_t ret = SUCCESS_CODE;
- for (int i = 0; i < NUMBER_OF_ARRAYS(g_chainTable); i++) {
- // skip unsupported for slip39 and non-public entries
- if (isSlip39 && (g_chainTable[i].cryptoKey == LEDGER_BITBOX02 || g_chainTable[i].cryptoKey == ZCASH_UFVK_ENCRYPTED)) {
- continue;
- }
-#ifdef WEB3_VERSION
- if (g_chainTable[i].cryptoKey == TON_CHECKSUM || g_chainTable[i].cryptoKey == TON_NATIVE) {
- continue;
- }
-#endif
- SimpleResponse_c_char* xPubResult = DeriveChainXpub(i, seed, seedLen, password, icarusMasterKey, ledgerBitbox02Key, isSlip39);
- if (g_chainTable[i].cryptoKey == RSA_KEY && xPubResult == NULL) {
- continue;
- }
- ASSERT(xPubResult);
- if (xPubResult->error_code != 0) {
- printf("get_extended_pubkey error\r\n");
- if (xPubResult->error_message != NULL) {
- printf("error code = %d\r\nerror msg is: %s\r\n", xPubResult->error_code, xPubResult->error_message);
- }
- ret = xPubResult->error_code;
- free_simple_response_c_char(xPubResult);
- break;
- }
- ASSERT(xPubResult->data);
- g_accountPublicInfo[i].value = SRAM_MALLOC(strnlen_s(xPubResult->data, SIMPLERESPONSE_C_CHAR_MAX_LEN) + 1);
- strcpy_s(g_accountPublicInfo[i].value, strnlen_s(xPubResult->data, SIMPLERESPONSE_C_CHAR_MAX_LEN) + 1, xPubResult->data);
- free_simple_response_c_char(xPubResult);
- }
- return ret;
-}
-
static int32_t DeriveMasterKeysIfNeeded(bool isBip39, uint8_t *entropy, uint8_t entropyLen, uint8_t accountIndex,
SimpleResponse_c_char **outCip3, SimpleResponse_c_char **outLedger)
{
diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c
index 051a46c..c9ca81d 100644
--- a/src/crypto/rsa.c
+++ b/src/crypto/rsa.c
@@ -64,6 +64,10 @@ Rsa_primes_t *FlashReadRsaPrimes(void)
ASSERT(Gd25FlashReadBuffer(GetRsaAddress(), fullData, sizeof(fullData)) == sizeof(fullData));
int len = (GetMnemonicType() == MNEMONIC_TYPE_BIP39) ? (int)sizeof(seed) : GetCurrentAccountEntropyLen();
+ if (SecretCacheGetPassword() == NULL) {
+ printf("password is empty\n");
+ break;
+ }
ret = GetAccountSeed(GetCurrentAccountIndex(), seed, SecretCacheGetPassword());
CHECK_ERRCODE_BREAK("GetAccountSeed", ret);
Why this scored 57/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.