feat(core): remove `tropic.get_certificate()`
What changed, and why it matters
This commit removes an unused function called tropic.get_certificate() from the Trezor firmware. The function was already a stub that did nothing useful: it returned success without actually fetching any certificate. The change is a cleanup, not a security fix, and does not appear to address any active vulnerability.
No action required; treat as routine code cleanup. If auditing, confirm no other code depends on the removed API and that the Tropic secure-element certificate is still retrieved through a different, properly implemented path if needed.
Security signals we found
Removal of dead/unimplemented Tropic secure-element certificate retrieval API
No functional certificate retrieval logic was present before the removal
No changelog entry and no security-related commit message
Evidence from the diff
The patch deletes the tropic_get_cert() API across the secure core, syscall, smcall, MicroPython binding, mock, and test layers. The original implementation in core/embed/sec/tropic/tropic.c was commented out and unconditionally returned LT_OK, so it was non-functional. Removing it reduces attack surface by eliminating a dead code path, but there is no evidence it was exploitable or that this change fixes a disclosed security issue.
Changed components
core/embed/sec/tropiccore/embed/sys/smcall/stm32core/embed/sys/syscall/stm32core/embed/upymod/modtrezorcryptocore/mocks/generated/trezorcrypto/tropic.pyicore/tests/test_trezor.crypto.tropic.pyInspect captured patch +0 / −93
diff --git a/core/embed/sec/tropic/inc/sec/tropic.h b/core/embed/sec/tropic/inc/sec/tropic.h
index 116b1984..ba2e2859 100644
--- a/core/embed/sec/tropic/inc/sec/tropic.h
+++ b/core/embed/sec/tropic/inc/sec/tropic.h
@@ -36,8 +36,6 @@ lt_handle_t* tropic_get_handle(void);
bool tropic_ping(const uint8_t* msg_out, uint8_t* msg_in, uint16_t msg_len);
-bool tropic_get_cert(uint8_t* buf, uint16_t buf_size);
-
bool tropic_ecc_key_generate(uint16_t slot_index);
bool tropic_ecc_sign(uint16_t key_slot_index, const uint8_t* dig,
diff --git a/core/embed/sec/tropic/tropic.c b/core/embed/sec/tropic/tropic.c
index e95acd35..68c86c77 100644
--- a/core/embed/sec/tropic/tropic.c
+++ b/core/embed/sec/tropic/tropic.c
@@ -121,18 +121,6 @@ bool tropic_ping(const uint8_t *msg_out, uint8_t *msg_in, uint16_t msg_len) {
return res == LT_OK;
}
-bool tropic_get_cert(uint8_t *buf, uint16_t buf_size) {
- tropic_driver_t *drv = &g_tropic_driver;
-
- if (!drv->initialized) {
- return false;
- }
-
- // TODO what is the new function
- // lt_ret_t res = lt_get_info_cert(&drv->handle, buf, buf_size);
- return LT_OK;
-}
-
bool tropic_ecc_key_generate(uint16_t slot_index) {
tropic_driver_t *drv = &g_tropic_driver;
diff --git a/core/embed/sys/smcall/stm32/smcall_dispatch.c b/core/embed/sys/smcall/stm32/smcall_dispatch.c
index aee4d153..4ad326fa 100644
--- a/core/embed/sys/smcall/stm32/smcall_dispatch.c
+++ b/core/embed/sys/smcall/stm32/smcall_dispatch.c
@@ -322,11 +322,6 @@ __attribute((no_stack_protector)) void smcall_handler(uint32_t *args,
args[0] = tropic_ping__verified(msg_out, msg_in, msg_len);
} break;
- case SMCALL_TROPIC_GET_CERT: {
- uint8_t *buf = (uint8_t *)args[0];
- uint16_t buf_size = (uint16_t)args[1];
- args[0] = tropic_get_cert__verified(buf, buf_size);
- } break;
case SMCALL_TROPIC_ECC_KEY_GENERATE: {
uint16_t slot_index = (uint16_t)args[0];
args[0] = tropic_ecc_key_generate__verified(slot_index);
diff --git a/core/embed/sys/smcall/stm32/smcall_numbers.h b/core/embed/sys/smcall/stm32/smcall_numbers.h
index e9df21a7..aa167403 100644
--- a/core/embed/sys/smcall/stm32/smcall_numbers.h
+++ b/core/embed/sys/smcall/stm32/smcall_numbers.h
@@ -89,7 +89,6 @@ typedef enum {
SMCALL_FIRMWARE_HASH_CONTINUE,
SMCALL_TROPIC_PING,
- SMCALL_TROPIC_GET_CERT,
SMCALL_TROPIC_ECC_KEY_GENERATE,
SMCALL_TROPIC_ECC_SIGN,
diff --git a/core/embed/sys/smcall/stm32/smcall_stubs.c b/core/embed/sys/smcall/stm32/smcall_stubs.c
index ffedfc39..d65f60fd 100644
--- a/core/embed/sys/smcall/stm32/smcall_stubs.c
+++ b/core/embed/sys/smcall/stm32/smcall_stubs.c
@@ -323,10 +323,6 @@ bool tropic_ping(const uint8_t *msg_in, uint8_t *msg_out, uint16_t msg_len) {
SMCALL_TROPIC_PING);
}
-bool tropic_get_cert(uint8_t *buf, uint16_t buf_size) {
- return (bool)smcall_invoke2((uint32_t)buf, buf_size, SMCALL_TROPIC_GET_CERT);
-}
-
bool tropic_ecc_key_generate(uint16_t slot_index) {
return (bool)smcall_invoke1((uint32_t)slot_index,
SMCALL_TROPIC_ECC_KEY_GENERATE);
diff --git a/core/embed/sys/smcall/stm32/smcall_verifiers.c b/core/embed/sys/smcall/stm32/smcall_verifiers.c
index 66a20343..ee94f13f 100644
--- a/core/embed/sys/smcall/stm32/smcall_verifiers.c
+++ b/core/embed/sys/smcall/stm32/smcall_verifiers.c
@@ -423,17 +423,6 @@ access_violation:
return false;
}
-bool tropic_get_cert__verified(uint8_t *buf, uint16_t buf_size) {
- if (!probe_write_access(buf, buf_size)) {
- goto access_violation;
- }
-
- return tropic_get_cert(buf, buf_size);
-access_violation:
- apptask_access_violation();
- return false;
-}
-
bool tropic_ecc_key_generate__verified(uint16_t slot_index) {
return tropic_ecc_key_generate(slot_index);
}
diff --git a/core/embed/sys/smcall/stm32/smcall_verifiers.h b/core/embed/sys/smcall/stm32/smcall_verifiers.h
index f11e3c3c..e23b3958 100644
--- a/core/embed/sys/smcall/stm32/smcall_verifiers.h
+++ b/core/embed/sys/smcall/stm32/smcall_verifiers.h
@@ -113,8 +113,6 @@ secbool firmware_get_vendor__verified(char *buff, size_t buff_size);
bool tropic_ping__verified(const uint8_t *msg_out, uint8_t *msg_in,
uint16_t msg_len);
-bool tropic_get_cert__verified(uint8_t *buf, uint16_t buf_size);
-
bool tropic_ecc_key_generate__verified(uint16_t slot_index);
bool tropic_ecc_sign__verified(uint16_t key_slot_index, const uint8_t *dig,
diff --git a/core/embed/sys/syscall/inc/sys/syscall_numbers.h b/core/embed/sys/syscall/inc/sys/syscall_numbers.h
index 4d8d1aec..183fa0e4 100644
--- a/core/embed/sys/syscall/inc/sys/syscall_numbers.h
+++ b/core/embed/sys/syscall/inc/sys/syscall_numbers.h
@@ -170,7 +170,6 @@ typedef enum {
SYSCALL_DMA2D_RGBA8888_BLEND_MONO8,
SYSCALL_TROPIC_PING,
- SYSCALL_TROPIC_GET_CERT,
SYSCALL_TROPIC_ECC_KEY_GENERATE,
SYSCALL_TROPIC_ECC_SIGN,
diff --git a/core/embed/sys/syscall/stm32/syscall_dispatch.c b/core/embed/sys/syscall/stm32/syscall_dispatch.c
index a1904441..8dbe4d49 100644
--- a/core/embed/sys/syscall/stm32/syscall_dispatch.c
+++ b/core/embed/sys/syscall/stm32/syscall_dispatch.c
@@ -863,11 +863,6 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
args[0] = tropic_ping__verified(msg_out, msg_in, msg_len);
} break;
- case SYSCALL_TROPIC_GET_CERT: {
- uint8_t *buf = (uint8_t *)args[0];
- uint16_t buf_size = (uint16_t)args[1];
- args[0] = tropic_get_cert__verified(buf, buf_size);
- } break;
case SYSCALL_TROPIC_ECC_KEY_GENERATE: {
uint16_t slot_index = (uint16_t)args[0];
args[0] = tropic_ecc_key_generate__verified(slot_index);
diff --git a/core/embed/sys/syscall/stm32/syscall_stubs.c b/core/embed/sys/syscall/stm32/syscall_stubs.c
index 3e5af3af..6d500662 100644
--- a/core/embed/sys/syscall/stm32/syscall_stubs.c
+++ b/core/embed/sys/syscall/stm32/syscall_stubs.c
@@ -836,11 +836,6 @@ bool tropic_ping(const uint8_t *msg_in, uint8_t *msg_out, uint16_t msg_len) {
SYSCALL_TROPIC_PING);
}
-bool tropic_get_cert(uint8_t *buf, uint16_t buf_size) {
- return (bool)syscall_invoke2((uint32_t)buf, buf_size,
- SYSCALL_TROPIC_GET_CERT);
-}
-
bool tropic_ecc_key_generate(uint16_t slot_index) {
return (bool)syscall_invoke1((uint32_t)slot_index,
SYSCALL_TROPIC_ECC_KEY_GENERATE);
diff --git a/core/embed/sys/syscall/stm32/syscall_verifiers.c b/core/embed/sys/syscall/stm32/syscall_verifiers.c
index 6153e0ff..d17d1ea7 100644
--- a/core/embed/sys/syscall/stm32/syscall_verifiers.c
+++ b/core/embed/sys/syscall/stm32/syscall_verifiers.c
@@ -1230,17 +1230,6 @@ access_violation:
return false;
}
-bool tropic_get_cert__verified(uint8_t *buf, uint16_t buf_size) {
- if (!probe_write_access(buf, buf_size)) {
- goto access_violation;
- }
-
- return tropic_get_cert(buf, buf_size);
-access_violation:
- apptask_access_violation();
- return false;
-}
-
bool tropic_ecc_key_generate__verified(uint16_t slot_index) {
return tropic_ecc_key_generate(slot_index);
}
diff --git a/core/embed/sys/syscall/stm32/syscall_verifiers.h b/core/embed/sys/syscall/stm32/syscall_verifiers.h
index 110dc7b9..2ef25363 100644
--- a/core/embed/sys/syscall/stm32/syscall_verifiers.h
+++ b/core/embed/sys/syscall/stm32/syscall_verifiers.h
@@ -295,8 +295,6 @@ bool button_get_event__verified(button_event_t *event);
bool tropic_ping__verified(const uint8_t *msg_out, uint8_t *msg_in,
uint16_t msg_len);
-bool tropic_get_cert__verified(uint8_t *buf, uint16_t buf_size);
-
bool tropic_ecc_key_generate__verified(uint16_t slot_index);
bool tropic_ecc_sign__verified(uint16_t key_slot_index, const uint8_t *dig,
diff --git a/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h b/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h
index 7b5dd4e2..702a0c34 100644
--- a/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h
+++ b/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h
@@ -58,28 +58,6 @@ STATIC mp_obj_t mod_trezorcrypto_tropic_ping(mp_obj_t message) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_tropic_ping_obj,
mod_trezorcrypto_tropic_ping);
-/// def get_certificate() -> bytes:
-/// """
-/// Return the chip's certificate.
-/// """
-STATIC mp_obj_t mod_trezorcrypto_tropic_get_certificate() {
- uint8_t X509_cert[CERT_SIZE] = {0};
- bool ret = tropic_get_cert(X509_cert, CERT_SIZE);
- if (!ret) {
- mp_raise_msg(&mp_type_TropicError,
- MP_ERROR_TEXT("tropic_get_cert failed."));
- }
-
- vstr_t vstr = {0};
- vstr_init_len(&vstr, CERT_SIZE);
-
- memcpy(vstr.buf, X509_cert, CERT_SIZE);
-
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorcrypto_tropic_get_certificate_obj,
- mod_trezorcrypto_tropic_get_certificate);
-
/// def key_generate(
/// key_index: int,
/// ) -> None:
@@ -143,8 +121,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_tropic_sign_obj,
STATIC const mp_rom_map_elem_t mod_trezorcrypto_tropic_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tropic)},
{MP_ROM_QSTR(MP_QSTR_ping), MP_ROM_PTR(&mod_trezorcrypto_tropic_ping_obj)},
- {MP_ROM_QSTR(MP_QSTR_get_certificate),
- MP_ROM_PTR(&mod_trezorcrypto_tropic_get_certificate_obj)},
{MP_ROM_QSTR(MP_QSTR_key_generate),
MP_ROM_PTR(&mod_trezorcrypto_tropic_key_generate_obj)},
{MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_trezorcrypto_tropic_sign_obj)},
diff --git a/core/mocks/generated/trezorcrypto/tropic.pyi b/core/mocks/generated/trezorcrypto/tropic.pyi
index 3fbd330d..2616d55c 100644
--- a/core/mocks/generated/trezorcrypto/tropic.pyi
+++ b/core/mocks/generated/trezorcrypto/tropic.pyi
@@ -10,11 +10,6 @@ class TropicError(Exception):
Test the session by pinging the chip.
"""
- def get_certificate() -> bytes:
- """
- Return the chip's certificate.
- """
-
def key_generate(
key_index: int,
) -> None:
diff --git a/core/tests/test_trezor.crypto.tropic.py b/core/tests/test_trezor.crypto.tropic.py
index 8c70989a..9a4c7da7 100644
--- a/core/tests/test_trezor.crypto.tropic.py
+++ b/core/tests/test_trezor.crypto.tropic.py
@@ -11,9 +11,6 @@ class TestCryptoTropic(unittest.TestCase):
self.assertEqual(tropic.ping(""), "")
self.assertEqual(tropic.ping("HeLlO!"), "HeLlO!")
- def test_get_certificate(self):
- self.assertEqual(len(tropic.get_certificate()), 512)
-
def test_sign(self):
try:
tropic.sign(0, "ASD")
Why this scored 12/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.