Fixing LEDGER_ASSERT failures with strings exceeding internal MESSAGE_SIZE hard-coded to 50
What changed, and why it matters
This commit shortens a number of internal error messages in Ledger's Bitcoin app so they no longer exceed a 50-character internal limit. The title says the long messages were causing LEDGER_ASSERT failures, which means the app could crash or refuse to proceed simply because a diagnostic string was too long. The change only rewords messages; it does not alter the underlying security checks or fix any vulnerability in the cryptographic logic.
Treat as a minor robustness fix. Verify that the shortened strings now fit within MESSAGE_SIZE and that LEDGER_ASSERT no longer fails on message formatting. No urgent security patch is indicated, but consider auditing the LEDGER_ASSERT macro to remove the hard-coded limit or handle truncation safely.
Security signals we found
Assertion message length exceeds internal buffer and triggers LEDGER_ASSERT failure
No change to cryptographic or signing logic; only diagnostic strings reworded
Potential for app crash/denial-of-service if long assertion messages are hit at runtime
Evidence from the diff
The patch modifies LEDGER_ASSERT message strings across wallet.h, crypto.c, policy.c and sign_psbt.c to fit within a hard-coded MESSAGE_SIZE of 50. In several places the word ‘Unexpected’ and explanatory clauses are removed. The assertions themselves (and the conditions they check) remain unchanged. The commit therefore addresses a message-formatting/length issue in the app’s internal error-reporting macro, not a flaw in the crypto or signing logic.
Changed components
src/common/wallet.hsrc/crypto.csrc/handler/lib/policy.csrc/handler/sign_psbt.cInspect captured patch +13 / −23
diff --git a/src/common/wallet.h b/src/common/wallet.h
index edc8090..bc12d8d 100644
--- a/src/common/wallet.h
+++ b/src/common/wallet.h
@@ -233,7 +233,7 @@ typedef enum {
else { \
int offset = (uint8_t *) obj - (uint8_t *) relative_ptr; \
LEDGER_ASSERT(offset >= 0 && offset < UINT16_MAX, \
- "Relative pointer's offset must be between 0 and 65535"); \
+ "Relative pointer offset must be in 0-65535 range"); \
relative_ptr->offset = (uint16_t) offset; \
} \
}
diff --git a/src/crypto.c b/src/crypto.c
index 22b7b11..41b5a55 100644
--- a/src/crypto.c
+++ b/src/crypto.c
@@ -168,7 +168,7 @@ int bip32_CKDpub(const serialized_extended_pubkey_t *parent,
void crypto_ripemd160(const uint8_t *in, uint16_t inlen, uint8_t out[static 20]) {
int res = cx_ripemd160_hash(in, inlen, out);
- LEDGER_ASSERT(res == CX_OK, "Unexpected error in ripemd160 computation. Returned: %d", res);
+ LEDGER_ASSERT(res == CX_OK, "Error in ripemd160 computation. Returned: %d", res);
}
void crypto_hash160(const uint8_t *in, uint16_t inlen, uint8_t out[static 20]) {
@@ -176,9 +176,7 @@ void crypto_hash160(const uint8_t *in, uint16_t inlen, uint8_t out[static 20]) {
uint8_t buffer[32];
int res = cx_hash_sha256(in, inlen, buffer, 32);
- LEDGER_ASSERT(res == CX_SHA256_SIZE,
- "Unexpected error in sha256 computation. Returned: %d",
- res);
+ LEDGER_ASSERT(res == CX_SHA256_SIZE, "Error in sha256 computation. Returned: %d", res);
crypto_ripemd160(buffer, 32, out);
}
@@ -233,13 +231,9 @@ void crypto_get_checksum(const uint8_t *in, uint16_t in_len, uint8_t out[static
uint8_t buffer[32];
size_t res;
res = cx_hash_sha256(in, in_len, buffer, 32);
- LEDGER_ASSERT(res == CX_SHA256_SIZE,
- "Unexpected error in sha256 computation. Returned: %d",
- res);
+ LEDGER_ASSERT(res == CX_SHA256_SIZE, "Error in sha256 computation. Returned: %d", res);
res = cx_hash_sha256(buffer, 32, buffer, 32);
- LEDGER_ASSERT(res == CX_SHA256_SIZE,
- "Unexpected error in sha256 computation. Returned: %d",
- res);
+ LEDGER_ASSERT(res == CX_SHA256_SIZE, "Error in sha256 computation. Returned: %d", res);
memmove(out, buffer, 4);
}
@@ -278,10 +272,7 @@ uint32_t crypto_get_master_key_fingerprint() {
uint8_t master_key_identifier[CX_RIPEMD160_SIZE] = {0};
int res = os_perso_get_master_key_identifier(master_key_identifier, CX_RIPEMD160_SIZE);
- LEDGER_ASSERT(
- res == CX_OK,
- "Unexpected error in os_perso_get_master_key_identifier computation. Returned: %d",
- res);
+ LEDGER_ASSERT(res == CX_OK, "Error in key_identifier computation. Returned: %d", res);
return read_u32_be(master_key_identifier, 0);
}
@@ -469,15 +460,15 @@ void crypto_tr_tagged_hash_init(cx_sha256_t *hash_context, const uint8_t *tag, u
uint8_t hashtag[32];
res = crypto_hash_update(&hash_context->header, tag, tag_len);
- LEDGER_ASSERT(res == CX_OK, "Unexpected error in sha256 computation. Returned: %d", res);
+ LEDGER_ASSERT(res == CX_OK, "Error in sha256 computation. Returned: %d", res);
res = crypto_hash_digest(&hash_context->header, hashtag, sizeof(hashtag));
- LEDGER_ASSERT(res == CX_OK, "Unexpected error in sha256 computation. Returned: %d", res);
+ LEDGER_ASSERT(res == CX_OK, "Error in sha256 computation. Returned: %d", res);
cx_sha256_init(hash_context);
res = crypto_hash_update(&hash_context->header, hashtag, sizeof(hashtag));
- LEDGER_ASSERT(res == CX_OK, "Unexpected error in sha256 computation. Returned: %d", res);
+ LEDGER_ASSERT(res == CX_OK, "Error in sha256 computation. Returned: %d", res);
res = crypto_hash_update(&hash_context->header, hashtag, sizeof(hashtag));
- LEDGER_ASSERT(res == CX_OK, "Unexpected error in sha256 computation. Returned: %d", res);
+ LEDGER_ASSERT(res == CX_OK, "Error in sha256 computation. Returned: %d", res);
}
void crypto_tr_tapleaf_hash_init(cx_sha256_t *hash_context) {
diff --git a/src/handler/lib/policy.c b/src/handler/lib/policy.c
index 6cd6613..3134476 100644
--- a/src/handler/lib/policy.c
+++ b/src/handler/lib/policy.c
@@ -1730,8 +1730,7 @@ int get_keyexpr_by_index(const policy_node_t *policy,
int ret = 0;
policy_node_scriptlist_t *cur_child = r_policy_node_scriptlist(&node->scriptlist);
for (int script_idx = 0; script_idx < node->n; script_idx++) {
- LEDGER_ASSERT(cur_child != NULL,
- "The script should always have exactly n child scripts");
+ LEDGER_ASSERT(cur_child != NULL, "The script must have exactly n child scripts");
found = i < (unsigned int) ret;
int ret_partial = get_keyexpr_by_index(r_policy_node(&cur_child->script),
diff --git a/src/handler/sign_psbt.c b/src/handler/sign_psbt.c
index 2cd5157..072d27e 100644
--- a/src/handler/sign_psbt.c
+++ b/src/handler/sign_psbt.c
@@ -1680,7 +1680,7 @@ static bool __attribute__((noinline)) sign_transaction_input(dispatcher_context_
// Sign as segwit input iff it has a witness utxo
if (!input->has_witnessUtxo) {
LEDGER_ASSERT(keyexpr_info->key_expression_ptr->type == KEY_EXPRESSION_NORMAL,
- "Only plain key expressions are valid for legacy inputs");
+ "Only plain key expressions for legacy inputs");
// sign legacy P2PKH or P2SH
// sign_non_witness(non_witness_utxo.vout[psbt.tx.input_[i].prevout.n].scriptPubKey, i)
@@ -1777,7 +1777,7 @@ static bool __attribute__((noinline)) sign_transaction_input(dispatcher_context_
uint8_t sighash[32];
if (segwit_version == 0) {
LEDGER_ASSERT(keyexpr_info->key_expression_ptr->type == KEY_EXPRESSION_NORMAL,
- "Only plain key expressions are valid for SegwitV0 inputs");
+ "Only plain key expressions for SegwitV0 inputs");
// segwitv0 inputs default to SIGHASH_ALL
uint8_t sighash_byte =
input->has_sighash_type ? (uint8_t) input->sighash_type : SIGHASH_ALL;
Why this scored 26/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.