feat(prodtest): Add Tropic random value and Tropic initialize to Tropic stress test
What changed, and why it matters
This commit is a routine feature addition to an internal production-test tool used during hardware manufacturing. It expands a stress test for the Tropic secure chip to also exercise chip initialization and random-number generation, and it cleans up how the emulator build chooses a network port for the simulated Tropic chip. There is no indication this fixes a security vulnerability or introduces a security-relevant weakness.
No security action required; treat as normal feature/refactor commit. If reviewing for code quality, verify that the moved `TROPIC_MODEL_PORT` parsing in `tropic.c` still rejects invalid port values and that the new stress-test arguments are documented consistently.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch modifies the prodtest firmware project’s Tropic stress-test CLI command to add lt_init()/tropic_init() and lt_random_value_get() loops, plus two new optional CLI arguments (init-iterations, rng-iterations). It also refactors emulator-only Tropic initialization: instead of callers passing a hardcoded port (28992) or an environment-derived port to tropic_init(port), all callers now invoke tropic_init(void), and the port selection logic (including TROPIC_MODEL_PORT environment variable parsing) is moved inside tropic.c. The public API in tropic.h is simplified to a single bool tropic_init(void) signature. No changelog entry is requested. No security bug, CVE, advisory, or researcher attribution is present in the commit materials.
Changed components
core/embed/projects/prodtest/cmd/prodtest_tropic.ccore/embed/projects/prodtest/main.ccore/embed/projects/unix/main_main.ccore/embed/projects/unix/rust_c_setup.ccore/embed/sec/tropic/inc/sec/tropic.hcore/embed/sec/tropic/tropic.cInspect captured patch +60 / −33
diff --git a/core/embed/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md
index 1395e051..e95a87a4 100644
--- a/core/embed/projects/prodtest/README.md
+++ b/core/embed/projects/prodtest/README.md
@@ -1464,7 +1464,7 @@ OK
### tropic-stress-test
-Runs a Tropic stress test that repeatedly calls `lt_session_start()`, `lt_mac_and_destroy()` and `lt_ecc_key_generate()` to test that Tropic doesn't enter alarm mode.
+Runs a Tropic stress test that repeatedly calls `lt_init()`, `lt_session_start()`, `lt_mac_and_destroy()`, `lt_ecc_key_generate()` and `lt_random_value_get()` to test that Tropic doesn't enter alarm mode.
### wpc-info
Retrieves detailed information from the wireless power receiver, including chip identification, firmware version, configuration settings, and error status.
diff --git a/core/embed/projects/prodtest/cmd/prodtest_tropic.c b/core/embed/projects/prodtest/cmd/prodtest_tropic.c
index 31a20f5e..11b72d0b 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_tropic.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_tropic.c
@@ -1633,17 +1633,23 @@ cleanup:
}
static void prodtest_tropic_stress_test(cli_t* cli) {
- if (cli_arg_count(cli) > 4) {
+ if (cli_arg_count(cli) > 6) {
cli_error_arg_count(cli);
return;
}
+ uint32_t init_iterations = 5;
uint32_t start_session_iterations = 10;
uint32_t mac_and_destroy_slot_count = TROPIC_MAC_AND_DESTROY_SLOT_COUNT;
uint32_t mac_and_destroy_per_slot_iterations = 3;
uint32_t signing_iterations = 10;
+ uint32_t rng_iterations = 10;
if (cli_arg_count(cli) != 0) {
+ if (!cli_arg_uint32(cli, "init-iterations", &init_iterations)) {
+ cli_error_arg(cli, "Expecting number of initialization iterations.");
+ return;
+ }
if (!cli_arg_uint32(cli, "start-session-iterations",
&start_session_iterations)) {
cli_error_arg(cli, "Expecting number of start-session iterations.");
@@ -1667,16 +1673,36 @@ static void prodtest_tropic_stress_test(cli_t* cli) {
cli_error_arg(cli, "Expecting number of signing iterations.");
return;
}
+ if (!cli_arg_uint32(cli, "rng-iterations", &rng_iterations)) {
+ cli_error_arg(cli, "Expecting number of RNG iterations.");
+ return;
+ }
}
+ cli_trace(cli, "Initialization iterations: %d", init_iterations);
cli_trace(cli, "Start-session iterations: %d", start_session_iterations);
cli_trace(cli, "MAC-and-destroy slot count: %d", mac_and_destroy_slot_count);
cli_trace(cli, "MAC-and-destroy iterations per slot: %d",
mac_and_destroy_per_slot_iterations);
cli_trace(cli, "Signing iterations: %d", signing_iterations);
+ cli_trace(cli, "RNG iterations: %d", rng_iterations);
g_tropic_handshake_state = TROPIC_HANDSHAKE_STATE_0;
+ // test Tropic gets initialized
+ for (int i = 0; i < init_iterations; i++) {
+ tropic_deinit();
+ if (!tropic_init()) {
+ cli_error(cli, CLI_ERROR, "Call #%d of `tropic_init()` failed", i + 1);
+ return;
+ }
+ if (!tropic_wait_for_ready(cli)) {
+ cli_error(cli, CLI_ERROR, "Call #%d of `tropic_wait_for_ready()` failed",
+ i + 1);
+ return;
+ }
+ }
+
lt_ret_t res = LT_FAIL;
lt_pkey_index_t pairing_key_index = -1;
@@ -1772,6 +1798,19 @@ static void prodtest_tropic_stress_test(cli_t* cli) {
return;
}
+ // Test lt_random_value_get()
+ for (int i = 0; i < rng_iterations; i++) {
+ uint8_t random_value[32] = {0};
+ res = lt_random_value_get(tropic_get_handle(), random_value,
+ sizeof(random_value));
+ if (res != LT_OK) {
+ cli_error(cli, CLI_ERROR,
+ "Call #%d of `lt_random_value_get()` failed with error '%s'",
+ i + 1, lt_ret_verbose(res));
+ return;
+ }
+ }
+
cli_ok(cli, "");
}
@@ -2132,7 +2171,7 @@ PRODTEST_CLI_CMD(
.name = "tropic-stress-test",
.func = prodtest_tropic_stress_test,
.info = "Run stress test for Tropic",
- .args = "[<start-session-iterations> <mac-and-destroy-slot-count> <mac-and-destroy-per-slot-iterations> <signing-iterations>]"
+ .args = "[<init-iterations> <start-session-iterations> <mac-and-destroy-slot-count> <mac-and-destroy-per-slot-iterations> <signing-iterations> <rng-iterations>]"
);
PRODTEST_CLI_CMD(
diff --git a/core/embed/projects/prodtest/main.c b/core/embed/projects/prodtest/main.c
index 25563d48..30fa0f16 100644
--- a/core/embed/projects/prodtest/main.c
+++ b/core/embed/projects/prodtest/main.c
@@ -193,11 +193,7 @@ static void drivers_init(void) {
ble_init();
#endif
#ifdef USE_TROPIC
-#ifdef TREZOR_EMULATOR
- tropic_init(28992);
-#else
tropic_init();
-#endif
tropic_wait_for_ready(NULL);
#endif
#ifdef USE_HW_REVISION
diff --git a/core/embed/projects/unix/main_main.c b/core/embed/projects/unix/main_main.c
index f4ec3c6d..57799aa5 100644
--- a/core/embed/projects/unix/main_main.c
+++ b/core/embed/projects/unix/main_main.c
@@ -63,22 +63,6 @@
#include <SDL.h>
-#ifdef USE_TROPIC
-static uint16_t get_tropic_model_port(void) {
- char *port_str = getenv("TROPIC_MODEL_PORT");
- if (port_str != NULL) {
- char *endptr;
- long port_long = strtol(port_str, &endptr, 10);
- if (*endptr != '\0' || port_long < 0 || port_long > 65535) {
- printf("FATAL: invalid TROPIC_MODEL_PORT\n");
- exit(1);
- }
- return (uint16_t)port_long;
- }
- return 28992;
-}
-#endif
-
static void drivers_deinit(void) { flash_deinit(); }
static void drivers_init(void) {
@@ -98,7 +82,7 @@ static void drivers_init(void) {
#endif
#ifdef USE_TROPIC
- tropic_init(get_tropic_model_port());
+ tropic_init();
#endif
usb_configure(NULL);
diff --git a/core/embed/projects/unix/rust_c_setup.c b/core/embed/projects/unix/rust_c_setup.c
index 92a180e5..24950e22 100644
--- a/core/embed/projects/unix/rust_c_setup.c
+++ b/core/embed/projects/unix/rust_c_setup.c
@@ -59,7 +59,7 @@ void rust_tests_c_setup(void) {
#endif
#ifdef USE_TROPIC
- tropic_init(28992);
+ tropic_init();
#endif
usb_configure(NULL);
diff --git a/core/embed/sec/tropic/inc/sec/tropic.h b/core/embed/sec/tropic/inc/sec/tropic.h
index 0937651f..8bcca32e 100644
--- a/core/embed/sec/tropic/inc/sec/tropic.h
+++ b/core/embed/sec/tropic/inc/sec/tropic.h
@@ -61,11 +61,7 @@
#ifdef KERNEL_MODE
-#ifdef TREZOR_EMULATOR
-bool tropic_init(uint16_t port);
-#else
bool tropic_init(void);
-#endif
void tropic01_reset(void);
diff --git a/core/embed/sec/tropic/tropic.c b/core/embed/sec/tropic/tropic.c
index 727ad96c..4deefa70 100644
--- a/core/embed/sec/tropic/tropic.c
+++ b/core/embed/sec/tropic/tropic.c
@@ -421,10 +421,22 @@ lt_ret_t lt_erase_and_write_R_config_retry(lt_handle_t *tropic_handle,
}
#ifdef TREZOR_EMULATOR
-bool tropic_init(uint16_t port) {
-#else
-bool tropic_init(void) {
+static uint16_t get_tropic_model_port(void) {
+ char *port_str = getenv("TROPIC_MODEL_PORT");
+ if (port_str != NULL) {
+ char *endptr;
+ long port_long = strtol(port_str, &endptr, 10);
+ if (*endptr != '\0' || port_long < 0 || port_long > 65535) {
+ printf("FATAL: invalid TROPIC_MODEL_PORT\n");
+ exit(1);
+ }
+ return (uint16_t)port_long;
+ }
+ return 28992;
+}
#endif
+
+bool tropic_init(void) {
tropic_driver_t *drv = &g_tropic_driver;
if (drv->initialized) {
@@ -433,7 +445,7 @@ bool tropic_init(void) {
#ifdef TREZOR_EMULATOR
drv->device.addr = inet_addr("127.0.0.1");
- drv->device.port = port;
+ drv->device.port = get_tropic_model_port();
drv->handle.l2.device = &drv->device;
#endif
Why this scored 15/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.