feat(core/prodtest): add commands for generic memory read/write
What changed, and why it matters
This commit adds two new commands to Trezor's production-test firmware: one that writes hex data into a small RAM buffer and one that reads it back. It is a test/debugging feature, not the normal wallet firmware users carry. The commands only touch a fixed 4 KB RAM buffer and do not directly read or write arbitrary memory addresses, so they appear limited in scope. However, adding interactive memory-style commands to a low-level test tool can be a stepping stone for deeper hardware attacks if combined with other vulnerabilities.
Treat this as a low-sensitivity test-infrastructure change. If the prodtest firmware is ever shipped to end users or left enabled on production devices, review whether these commands should be gated or removed. Verify the README buffer-size description matches the code (4 KB vs 8 KB). Confirm `cli_arg_hex` correctly rejects over-long input and malformed hex. No immediate patch is required solely based on this diff.
Security signals we found
New interactive memory read/write commands added to a low-level test/debug firmware
Static RAM buffer used as a data sink/source for CLI input/output
Documentation/code size mismatch: README says 8 kB, code defines 4 kB
No input length or address validation issues visible, because the write is bounded by the fixed buffer size
Feature is in prodtest firmware, not main wallet firmware, reducing end-user exposure
Evidence from the diff
The patch introduces prodtest-mem-write and prodtest-mem-read CLI commands in core/embed/projects/prodtest/cmd/prodtest_prodtest.c. prodtest-mem-write parses a hex argument via cli_arg_hex into a static 4 KB mem_buffer, bounded by MEM_BUFFER_SIZE. prodtest_mem_read echoes the stored bytes via cli_ok_hexdata. The README documents the commands as writing to an 8 KB RAM buffer, while the code defines MEM_BUFFER_SIZE as 4 KB. There is no address parameter, no direct MMIO access, and no obvious buffer overflow because the parser is given the buffer size. The change is confined to the prodtest project, a manufacturing/test firmware image.
Changed components
core/embed/projects/prodtest/cmd/prodtest_prodtest.ccore/embed/projects/prodtest/README.mdTrezor production-test firmware CLIInspect captured patch +62 / −0
diff --git a/core/embed/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md
index 9973df4bd..1da37d634 100644
--- a/core/embed/projects/prodtest/README.md
+++ b/core/embed/projects/prodtest/README.md
@@ -746,6 +746,26 @@ prodtest-homescreen
OK
```
+### prodtest-mem-write
+Parses hex data from the argument and stores it into an 8kB RAM buffer.
+
+`prodtest-mem-write <hexdata>`
+
+Example:
+```
+prodtest-mem-write 01020304
+OK
+```
+
+### prodtest-mem-read
+Reads back the data currently stored in the RAM buffer and outputs it as hex.
+
+Example:
+```
+prodtest-mem-read
+OK 01020304
+```
+
### secrets-init
Generates random secrets and stores them in the protected storage.
diff --git a/core/embed/projects/prodtest/cmd/prodtest_prodtest.c b/core/embed/projects/prodtest/cmd/prodtest_prodtest.c
index bfa1cd34e..c97c35c07 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_prodtest.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_prodtest.c
@@ -32,6 +32,10 @@
#include <version.h>
+#define MEM_BUFFER_SIZE (4 * 1024)
+static uint8_t mem_buffer[MEM_BUFFER_SIZE];
+static size_t mem_buffer_len = 0;
+
static void prodtest_prodtest_intro(cli_t* cli) {
cli_trace(cli, "Welcome to Trezor %s Production Test Firmware v%d.%d.%d.%d.",
MODEL_NAME, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH,
@@ -85,6 +89,30 @@ static void prodtest_homescreen(cli_t* cli) {
cli_ok(cli, "");
}
+static void prodtest_mem_write(cli_t* cli) {
+ if (cli_arg_count(cli) != 1) {
+ cli_error_arg_count(cli);
+ return;
+ }
+
+ if (!cli_arg_hex(cli, "hexdata", mem_buffer, MEM_BUFFER_SIZE,
+ &mem_buffer_len)) {
+ cli_error_arg(cli, "Failed to parse hex data.");
+ return;
+ }
+
+ cli_ok(cli, "");
+}
+
+static void prodtest_mem_read(cli_t* cli) {
+ if (cli_arg_count(cli) > 0) {
+ cli_error_arg_count(cli);
+ return;
+ }
+
+ cli_ok_hexdata(cli, mem_buffer, mem_buffer_len);
+}
+
// clang-format off
PRODTEST_CLI_CMD(
@@ -114,3 +142,17 @@ PRODTEST_CLI_CMD(
.info = "Shows prodtest homescreen",
.args = ""
);
+
+PRODTEST_CLI_CMD(
+ .name = "prodtest-mem-write",
+ .func = prodtest_mem_write,
+ .info = "Write data into RAM buffer",
+ .args = "<hexdata>"
+);
+
+PRODTEST_CLI_CMD(
+ .name = "prodtest-mem-read",
+ .func = prodtest_mem_read,
+ .info = "Read data from RAM buffer",
+ .args = ""
+);
Why this scored 23/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.