What changed, and why it matters
This commit updates Trezor firmware to match a newer version of an external secure-chip library called libtropic. The main user-visible change is that a cryptographic signing function no longer takes a caller-supplied signature-buffer length; instead the firmware always uses a fixed, library-defined size. The patch also swaps the low-level random-number callback to a different API that the updated library expects. There is no claim in the commit that this fixes a security bug; it reads as a compatibility update after a dependency upgrade.
Treat as a routine dependency-compatibility patch. Reviewers should confirm that ECDSA_RAW_SIGNATURE_SIZE matches the fixed signature size expected by the updated libtropic EdDSA implementation and that the new random_buffer callback is seeded correctly. No urgent security response is indicated by the commit itself.
Security signals we found
Removal of caller-supplied output-buffer length from a privileged signing syscall/smcall
Verifier now hard-codes output-buffer probe size to ECDSA_RAW_SIGNATURE_SIZE
Low-level randomness source callback changed to random_buffer after library update
No changelog entry and no security framing in commit message
Evidence from the diff
The diff adapts the Tropic secure-element integration to an updated libtropic API. Key changes: (1) tropic_ecc_sign and its syscall/smcall wrappers drop the sig_len parameter and now size the output buffer with ECDSA_RAW_SIGNATURE_SIZE. (2) lt_port_random_bytes is rewritten to match the new libtropic prototype lt_port_random_bytes(lt_l2_state_t *s2, void *buff, size_t count) and now calls random_buffer. (3) The MicroPython binding uses ECDSA_RAW_SIGNATURE_SIZE instead of a local SIG_SIZE 64. The change from a caller-controlled length to a fixed constant removes one potential mismatch between caller intent and buffer size, but the commit message frames this as ‘fixes after libtropic update’, not as a vulnerability fix.
Changed components
core/embed/sec/tropic/tropic.ccore/embed/sec/tropic/stm32/tropic01.ccore/embed/sys/smcall/stm32/smcall_dispatch.ccore/embed/sys/smcall/stm32/smcall_stubs.ccore/embed/sys/smcall/stm32/smcall_verifiers.ccore/embed/sys/syscall/stm32/syscall_dispatch.ccore/embed/sys/syscall/stm32/syscall_stubs.ccore/embed/sys/syscall/stm32/syscall_verifiers.ccore/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.hInspect captured patch +29 / −38
diff --git a/core/embed/sec/tropic/inc/sec/tropic.h b/core/embed/sec/tropic/inc/sec/tropic.h
index ba2e2859..312ca35f 100644
--- a/core/embed/sec/tropic/inc/sec/tropic.h
+++ b/core/embed/sec/tropic/inc/sec/tropic.h
@@ -39,4 +39,4 @@ bool tropic_ping(const uint8_t* msg_out, uint8_t* msg_in, uint16_t msg_len);
bool tropic_ecc_key_generate(uint16_t slot_index);
bool tropic_ecc_sign(uint16_t key_slot_index, const uint8_t* dig,
- uint16_t dig_len, uint8_t* sig, uint16_t sig_len);
+ uint16_t dig_len, uint8_t* sig);
diff --git a/core/embed/sec/tropic/stm32/tropic01.c b/core/embed/sec/tropic/stm32/tropic01.c
index 3687173c..d48c1c8c 100644
--- a/core/embed/sec/tropic/stm32/tropic01.c
+++ b/core/embed/sec/tropic/stm32/tropic01.c
@@ -27,6 +27,8 @@
#include <sec/tropic.h>
#include <sys/systick.h>
+#include "rand.h"
+
typedef struct {
bool initialized;
SPI_HandleTypeDef spi;
@@ -183,13 +185,9 @@ lt_ret_t lt_port_delay(lt_handle_t *h, uint32_t ms) {
return LT_OK;
}
-lt_ret_t lt_port_random_bytes(uint32_t *buff, uint16_t len) {
- while (len > 0) {
- uint32_t random = rng_get();
- *buff = random;
- buff++;
- len--;
- }
+lt_ret_t lt_port_random_bytes(lt_l2_state_t *s2, void *buff, size_t count) {
+ (void)s2;
+ random_buffer((uint8_t *)buff, count);
return LT_OK;
}
diff --git a/core/embed/sec/tropic/tropic.c b/core/embed/sec/tropic/tropic.c
index 68c86c77..33ad962d 100644
--- a/core/embed/sec/tropic/tropic.c
+++ b/core/embed/sec/tropic/tropic.c
@@ -137,7 +137,7 @@ bool tropic_ecc_key_generate(uint16_t slot_index) {
}
bool tropic_ecc_sign(uint16_t key_slot_index, const uint8_t *dig,
- uint16_t dig_len, uint8_t *sig, uint16_t sig_len) {
+ uint16_t dig_len, uint8_t *sig) {
tropic_driver_t *drv = &g_tropic_driver;
if (!drv->initialized) {
@@ -151,7 +151,7 @@ bool tropic_ecc_sign(uint16_t key_slot_index, const uint8_t *dig,
lt_ret_t res =
lt_ecc_eddsa_sign(&drv->handle, key_slot_index, dig, dig_len, sig);
if (res != LT_OK) {
- memzero(sig, sig_len);
+ memzero(sig, ECDSA_RAW_SIGNATURE_SIZE);
return false;
}
diff --git a/core/embed/sys/smcall/stm32/smcall_dispatch.c b/core/embed/sys/smcall/stm32/smcall_dispatch.c
index 8ed9ecd2..740d087a 100644
--- a/core/embed/sys/smcall/stm32/smcall_dispatch.c
+++ b/core/embed/sys/smcall/stm32/smcall_dispatch.c
@@ -332,9 +332,7 @@ __attribute((no_stack_protector)) void smcall_handler(uint32_t *args,
const uint8_t *dig = (const uint8_t *)args[1];
uint16_t dig_len = (uint16_t)args[2];
uint8_t *sig = (uint8_t *)args[3];
- uint16_t sig_len = (uint16_t)args[4];
- args[0] =
- tropic_ecc_sign__verified(key_slot_index, dig, dig_len, sig, sig_len);
+ args[0] = tropic_ecc_sign__verified(key_slot_index, dig, dig_len, sig);
} break;
#endif
diff --git a/core/embed/sys/smcall/stm32/smcall_stubs.c b/core/embed/sys/smcall/stm32/smcall_stubs.c
index d65f60fd..28bdc167 100644
--- a/core/embed/sys/smcall/stm32/smcall_stubs.c
+++ b/core/embed/sys/smcall/stm32/smcall_stubs.c
@@ -329,9 +329,9 @@ bool tropic_ecc_key_generate(uint16_t slot_index) {
}
bool tropic_ecc_sign(uint16_t key_slot_index, const uint8_t *dig,
- uint16_t dig_len, uint8_t *sig, uint16_t sig_len) {
- return (bool)smcall_invoke5((uint32_t)key_slot_index, (uint32_t)dig, dig_len,
- (uint32_t)sig, sig_len, SMCALL_TROPIC_ECC_SIGN);
+ uint16_t dig_len, uint8_t *sig) {
+ return (bool)smcall_invoke4((uint32_t)key_slot_index, (uint32_t)dig, dig_len,
+ (uint32_t)sig, SMCALL_TROPIC_ECC_SIGN);
}
#endif
diff --git a/core/embed/sys/smcall/stm32/smcall_verifiers.c b/core/embed/sys/smcall/stm32/smcall_verifiers.c
index ee94f13f..ff1fc96d 100644
--- a/core/embed/sys/smcall/stm32/smcall_verifiers.c
+++ b/core/embed/sys/smcall/stm32/smcall_verifiers.c
@@ -406,6 +406,7 @@ access_violation:
#ifdef USE_TROPIC
#include <sec/tropic.h>
+#include "ecdsa.h"
bool tropic_ping__verified(const uint8_t *msg_out, uint8_t *msg_in,
uint16_t msg_len) {
@@ -428,17 +429,16 @@ bool tropic_ecc_key_generate__verified(uint16_t slot_index) {
}
bool tropic_ecc_sign__verified(uint16_t key_slot_index, const uint8_t *dig,
- uint16_t dig_len, uint8_t *sig,
- uint16_t sig_len) {
+ uint16_t dig_len, uint8_t *sig) {
if (!probe_read_access(dig, dig_len)) {
goto access_violation;
}
- if (!probe_write_access(sig, sig_len)) {
+ if (!probe_write_access(sig, ECDSA_RAW_SIGNATURE_SIZE)) {
goto access_violation;
}
- return tropic_ecc_sign(key_slot_index, dig, dig_len, sig, sig_len);
+ return tropic_ecc_sign(key_slot_index, dig, dig_len, sig);
access_violation:
apptask_access_violation();
return false;
diff --git a/core/embed/sys/smcall/stm32/smcall_verifiers.h b/core/embed/sys/smcall/stm32/smcall_verifiers.h
index e23b3958..a3f62723 100644
--- a/core/embed/sys/smcall/stm32/smcall_verifiers.h
+++ b/core/embed/sys/smcall/stm32/smcall_verifiers.h
@@ -116,8 +116,7 @@ bool tropic_ping__verified(const uint8_t *msg_out, uint8_t *msg_in,
bool tropic_ecc_key_generate__verified(uint16_t slot_index);
bool tropic_ecc_sign__verified(uint16_t key_slot_index, const uint8_t *dig,
- uint16_t dig_len, uint8_t *sig,
- uint16_t sig_len);
+ uint16_t dig_len, uint8_t *sig);
#endif
diff --git a/core/embed/sys/syscall/stm32/syscall_dispatch.c b/core/embed/sys/syscall/stm32/syscall_dispatch.c
index b4ff882a..e93cf857 100644
--- a/core/embed/sys/syscall/stm32/syscall_dispatch.c
+++ b/core/embed/sys/syscall/stm32/syscall_dispatch.c
@@ -873,9 +873,7 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
const uint8_t *dig = (const uint8_t *)args[1];
uint16_t dig_len = (uint16_t)args[2];
uint8_t *sig = (uint8_t *)args[3];
- uint16_t sig_len = (uint16_t)args[4];
- args[0] =
- tropic_ecc_sign__verified(key_slot_index, dig, dig_len, sig, sig_len);
+ args[0] = tropic_ecc_sign__verified(key_slot_index, dig, dig_len, sig);
} break;
#endif
diff --git a/core/embed/sys/syscall/stm32/syscall_stubs.c b/core/embed/sys/syscall/stm32/syscall_stubs.c
index 6d500662..12e2150e 100644
--- a/core/embed/sys/syscall/stm32/syscall_stubs.c
+++ b/core/embed/sys/syscall/stm32/syscall_stubs.c
@@ -842,9 +842,9 @@ bool tropic_ecc_key_generate(uint16_t slot_index) {
}
bool tropic_ecc_sign(uint16_t key_slot_index, const uint8_t *dig,
- uint16_t dig_len, uint8_t *sig, uint16_t sig_len) {
- return (bool)syscall_invoke5((uint32_t)key_slot_index, (uint32_t)dig, dig_len,
- (uint32_t)sig, sig_len, SYSCALL_TROPIC_ECC_SIGN);
+ uint16_t dig_len, uint8_t *sig) {
+ return (bool)syscall_invoke4((uint32_t)key_slot_index, (uint32_t)dig, dig_len,
+ (uint32_t)sig, SYSCALL_TROPIC_ECC_SIGN);
}
#endif
diff --git a/core/embed/sys/syscall/stm32/syscall_verifiers.c b/core/embed/sys/syscall/stm32/syscall_verifiers.c
index d17d1ea7..b2802dd3 100644
--- a/core/embed/sys/syscall/stm32/syscall_verifiers.c
+++ b/core/embed/sys/syscall/stm32/syscall_verifiers.c
@@ -1213,6 +1213,7 @@ access_violation:
#ifdef USE_TROPIC
#include <sec/tropic.h>
+#include "ecdsa.h"
bool tropic_ping__verified(const uint8_t *msg_out, uint8_t *msg_in,
uint16_t msg_len) {
@@ -1235,17 +1236,16 @@ bool tropic_ecc_key_generate__verified(uint16_t slot_index) {
}
bool tropic_ecc_sign__verified(uint16_t key_slot_index, const uint8_t *dig,
- uint16_t dig_len, uint8_t *sig,
- uint16_t sig_len) {
+ uint16_t dig_len, uint8_t *sig) {
if (!probe_read_access(dig, dig_len)) {
goto access_violation;
}
- if (!probe_write_access(sig, sig_len)) {
+ if (!probe_write_access(sig, ECDSA_RAW_SIGNATURE_SIZE)) {
goto access_violation;
}
- return tropic_ecc_sign(key_slot_index, dig, dig_len, sig, sig_len);
+ return tropic_ecc_sign(key_slot_index, dig, dig_len, sig);
access_violation:
apptask_access_violation();
return false;
diff --git a/core/embed/sys/syscall/stm32/syscall_verifiers.h b/core/embed/sys/syscall/stm32/syscall_verifiers.h
index 2ef25363..a2a62177 100644
--- a/core/embed/sys/syscall/stm32/syscall_verifiers.h
+++ b/core/embed/sys/syscall/stm32/syscall_verifiers.h
@@ -298,8 +298,7 @@ bool tropic_ping__verified(const uint8_t *msg_out, uint8_t *msg_in,
bool tropic_ecc_key_generate__verified(uint16_t slot_index);
bool tropic_ecc_sign__verified(uint16_t key_slot_index, const uint8_t *dig,
- uint16_t dig_len, uint8_t *sig,
- uint16_t sig_len);
+ uint16_t dig_len, uint8_t *sig);
#endif
diff --git a/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h b/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h
index 702a0c34..aa4ec05e 100644
--- a/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h
+++ b/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h
@@ -30,7 +30,6 @@ MP_DEFINE_EXCEPTION(TropicError, Exception)
#define PING_MSG_MAX_LEN 64
#define ECC_SLOT_COUNT 32
-#define SIG_SIZE 64
#define CERT_SIZE 512
@@ -102,17 +101,17 @@ STATIC mp_obj_t mod_trezorcrypto_tropic_sign(mp_obj_t key_index,
}
vstr_t sig = {0};
- vstr_init_len(&sig, SIG_SIZE);
+ vstr_init_len(&sig, ECDSA_RAW_SIGNATURE_SIZE);
bool ret = tropic_ecc_sign(idx, (const uint8_t *)dig.buf, dig.len,
- ((uint8_t *)sig.buf), SIG_SIZE);
+ ((uint8_t *)sig.buf));
if (!ret) {
vstr_clear(&sig);
mp_raise_msg(&mp_type_TropicError,
MP_ERROR_TEXT("lt_ecc_eddsa_sign failed."));
}
- sig.len = SIG_SIZE;
+ sig.len = ECDSA_RAW_SIGNATURE_SIZE;
return mp_obj_new_str_from_vstr(&mp_type_bytes, &sig);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_tropic_sign_obj,
Why this scored 25/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.