feat(core/prodtest): Reboot Tropic in tropic-set-sensors.
What changed, and why it matters
This commit changes a factory/production-test command for the Tropic secure chip inside Trezor devices. The command now reboots the chip after changing sensor settings, makes the sensor-setting argument optional (defaulting to enabling all sensors), and avoids erasing key slots when running in a special factory session. It appears to be a functional/operational improvement for the production line rather than a fix for an exploitable security vulnerability in end-user devices.
Treat as a routine production-test feature/improvement. Review whether defaulting to enabling all sensors and skipping slot erase under the factory pairing key are intentional and documented production-line requirements. No end-user action is indicated.
Security signals we found
Change in production-test secure-element command behavior
Default argument now enables all sensors (0x00000000)
Conditional erase of ECC/data/MAC slots based on pairing key slot
Added reboot and re-initialization after sensor configuration write
No mention of vulnerability, CVE, or security fix in commit message or diff
Evidence from the diff
The patch modifies prodtest_tropic_set_sensors() in the Trezor production-test firmware. Key changes: (1) argument count check relaxed from exactly 1 to 0 or 1, with a default new_sensors_config = 0 (enables all sensors); (2) the previous unconditional tropic_erase_all_slots_internal() call is now skipped when pairing_key_index == TROPIC_FACTORY_PAIRING_KEY_SLOT; (3) after writing the sensor configuration, the code calls lt_reboot(tropic_handle, TR01_REBOOT) and then re-initializes the Tropic stack so the new configuration takes effect. A new error code PRODTEST_ERR_TROPIC_SENSORS_REBOOT is added. The command is part of the prodtest project, not the end-user wallet firmware.
Changed components
core/embed/projects/prodtest/cmd/prodtest_tropic.ccore/embed/projects/prodtest/README.mdcore/embed/projects/prodtest/error_codes.jsoncore/embed/projects/prodtest/prodtest_error_codes.hInspect captured patch +60 / −30
diff --git a/core/embed/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md
index 9cdc9f66..067e1391 100644
--- a/core/embed/projects/prodtest/README.md
+++ b/core/embed/projects/prodtest/README.md
@@ -1358,7 +1358,9 @@ OK <hexadecimal string>
### tropic-set-sensors
-Erases all ECC key slots, data slots and MAC & Destroy slots and then sets the reversible configuration of Tropic sensors to the input value.
+Erases all ECC key slots, data slots and MAC & Destroy slots if Tropic is paired. Sets the reversible configuration of Tropic sensors to the input value and reboots the chip so the new configuration takes effect.
+
+The optional argument defaults to `00000000`, which enables all sensors.
Example:
```
diff --git a/core/embed/projects/prodtest/cmd/prodtest_tropic.c b/core/embed/projects/prodtest/cmd/prodtest_tropic.c
index 5acbb883..212c2b03 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_tropic.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_tropic.c
@@ -2841,49 +2841,57 @@ static void prodtest_tropic_erase_all_slots(cli_t* cli) {
}
static void prodtest_tropic_set_sensors(cli_t* cli) {
- if (cli_arg_count(cli) != 1) {
+ if (cli_arg_count(cli) > 1) {
cli_error_arg_count(cli);
return;
}
- uint8_t input[4] = {0};
- size_t input_length = 0;
- if (!cli_arg_hex(cli, "hex-data", input, sizeof(input), &input_length)) {
- if (input_length == sizeof(input)) {
- cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_INPUT_LONG, "Input too long.");
- } else {
- cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_HEX_DECODE,
- "Hexadecimal decoding error.");
+ // Default to 0x00000000, which enables all sensors.
+ uint32_t new_sensors_config = 0;
+ if (cli_arg_count(cli) == 1) {
+ uint8_t input[4] = {0};
+ size_t input_length = 0;
+ if (!cli_arg_hex(cli, "hex-data", input, sizeof(input), &input_length)) {
+ if (input_length == sizeof(input)) {
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_INPUT_LONG,
+ "Input too long.");
+ } else {
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_HEX_DECODE,
+ "Hexadecimal decoding error.");
+ }
+ return;
}
- return;
- }
- if (input_length != sizeof(input)) {
- cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_INPUT_LEN,
- "Expected 4 bytes (8 hex digits) for uint32.");
- return;
- }
+ if (input_length != sizeof(input)) {
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_INPUT_LEN,
+ "Expected 4 bytes (8 hex digits) for uint32.");
+ return;
+ }
- uint32_t new_sensors_config =
- ((uint32_t)input[0] << 24) | ((uint32_t)input[1] << 16) |
- ((uint32_t)input[2] << 8) | ((uint32_t)input[3]);
+ new_sensors_config = ((uint32_t)input[0] << 24) |
+ ((uint32_t)input[1] << 16) |
+ ((uint32_t)input[2] << 8) | ((uint32_t)input[3]);
+ }
- if (!privileged_session_start(cli)) {
- cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_SESSION,
- "`privileged_session_start()` failed.");
+ lt_pkey_index_t pairing_key_index = 0;
+ if (!tropic_ensure_session(cli, &pairing_key_index)) {
return;
}
lt_handle_t* tropic_handle = tropic_get_handle();
- lt_ret_t ret = tropic_erase_all_slots_internal(cli, tropic_handle);
- if (ret != LT_OK) {
- cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_ERASE, "Erase operation failed");
- return;
+ // No need to wipe under a factory session. Tropic is unprovisioned.
+ if (pairing_key_index != TROPIC_FACTORY_PAIRING_KEY_SLOT) {
+ lt_ret_t ret = tropic_erase_all_slots_internal(cli, tropic_handle);
+ if (ret != LT_OK) {
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_ERASE,
+ "Erase operation failed");
+ return;
+ }
}
struct lt_config_t configuration = {0};
- ret = lt_read_whole_R_config_retry(tropic_handle, &configuration);
+ lt_ret_t ret = lt_read_whole_R_config_retry(tropic_handle, &configuration);
if (ret != LT_OK) {
cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_READ_CONFIG,
"`lt_read_whole_R_config()` failed with error %s",
@@ -2919,6 +2927,20 @@ static void prodtest_tropic_set_sensors(cli_t* cli) {
return;
}
+ // The sensor configuration only takes effect after a reboot.
+ ret = lt_reboot(tropic_handle, TR01_REBOOT);
+ if (ret != LT_OK) {
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_REBOOT,
+ "`lt_reboot()` failed with error %s", lt_ret_verbose(ret));
+ return;
+ }
+ tropic_deinit();
+ if (!tropic_init() || !tropic_wait_for_ready(cli)) {
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_REBOOT,
+ "Re-initialization after reboot failed.");
+ return;
+ }
+
cli_ok(cli, "");
}
@@ -3193,8 +3215,8 @@ PRODTEST_CLI_CMD(
PRODTEST_CLI_CMD(
.name = "tropic-set-sensors",
.func = prodtest_tropic_set_sensors,
- .info = "Set the reversible configuration of the sensors in Tropic",
- .args = "<hex-data>"
+ .info = "Set the reversible sensor configuration and reboot Tropic to apply it. Enables all sensors by default.",
+ .args = "[<hex-data>]"
);
PRODTEST_CLI_CMD(
diff --git a/core/embed/projects/prodtest/error_codes.json b/core/embed/projects/prodtest/error_codes.json
index cb315cb6..597787ec 100644
--- a/core/embed/projects/prodtest/error_codes.json
+++ b/core/embed/projects/prodtest/error_codes.json
@@ -1631,6 +1631,11 @@
"name": "PRODTEST_ERR_TROPIC_EXPLICIT_SLOT_RANGE",
"module": "tropic"
},
+ {
+ "code": 20139,
+ "name": "PRODTEST_ERR_TROPIC_SENSORS_REBOOT",
+ "module": "tropic"
+ },
{
"code": 21010,
"name": "PRODTEST_ERR_UNIT_TEST_FAILED",
diff --git a/core/embed/projects/prodtest/prodtest_error_codes.h b/core/embed/projects/prodtest/prodtest_error_codes.h
index c41e58d8..8c475fb8 100644
--- a/core/embed/projects/prodtest/prodtest_error_codes.h
+++ b/core/embed/projects/prodtest/prodtest_error_codes.h
@@ -397,6 +397,7 @@ typedef enum {
PRODTEST_ERR_TROPIC_TEST_RNG_REPEAT = 20136,
PRODTEST_ERR_TROPIC_EXPLICIT_SLOT_COUNT = 20137,
PRODTEST_ERR_TROPIC_EXPLICIT_SLOT_RANGE = 20138,
+ PRODTEST_ERR_TROPIC_SENSORS_REBOOT = 20139,
// === unit-test (21000–21999) ===
PRODTEST_ERR_UNIT_TEST_FAILED = 21010,
Why this scored 22/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.