chore(core): export `memzero()` via `trezor.utils`
What changed, and why it matters
This commit simply exposes an existing secure memory-clearing function to more parts of the Trezor firmware. It does not fix a bug or change behavior users can observe. It is a routine code cleanup (a 'chore') with no direct security impact on its own.
No action required. Treat as routine maintenance. Future code reviews should verify that callers of `utils.memzero()` use it appropriately to clear sensitive material such as private keys or seed phrases.
Security signals we found
Adds secure memory-zeroing primitive to Python API
No vulnerability fix or behavior change in existing code
Tagged as chore with [no changelog]
Evidence from the diff
The change adds a C implementation of memzero() in the trezorutils MicroPython module and re-exports it through trezor.utils. The function wraps the existing memzero() C primitive to zero out a writable buffer (bytearray or memoryview). It includes a generated stub and a unit test verifying that zeroing works on both full buffers and memoryview slices. There is no vulnerability being patched here; the commit only makes a security-relevant primitive more accessible to Python code.
Changed components
core/embed/upymod/modtrezorutils/modtrezorutils.ccore/src/trezor/utils.pycore/mocks/generated/trezorutils.pyicore/tests/test_trezor.utils.pyInspect captured patch +33 / −0
diff --git a/core/embed/upymod/modtrezorutils/modtrezorutils.c b/core/embed/upymod/modtrezorutils/modtrezorutils.c
index 061033604..9c3e3c071 100644
--- a/core/embed/upymod/modtrezorutils/modtrezorutils.c
+++ b/core/embed/upymod/modtrezorutils/modtrezorutils.c
@@ -121,6 +121,21 @@ STATIC mp_obj_t mod_trezorutils_memcpy(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorutils_memcpy_obj, 4, 5,
mod_trezorutils_memcpy);
+/// def memzero(
+/// dst: bytearray | memoryview,
+/// ) -> None:
+/// """
+/// Zeroes all bytes at `dst`.
+/// """
+STATIC mp_obj_t mod_trezorutils_memzero(const mp_obj_t dst) {
+ mp_buffer_info_t buf = {0};
+ mp_get_buffer_raise(dst, &buf, MP_BUFFER_WRITE);
+ memzero(buf.buf, buf.len);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorutils_memzero_obj,
+ mod_trezorutils_memzero);
+
/// def halt(msg: str | None = None) -> None:
/// """
/// Halts execution.
@@ -628,6 +643,7 @@ STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorutils)},
{MP_ROM_QSTR(MP_QSTR_consteq), MP_ROM_PTR(&mod_trezorutils_consteq_obj)},
{MP_ROM_QSTR(MP_QSTR_memcpy), MP_ROM_PTR(&mod_trezorutils_memcpy_obj)},
+ {MP_ROM_QSTR(MP_QSTR_memzero), MP_ROM_PTR(&mod_trezorutils_memzero_obj)},
{MP_ROM_QSTR(MP_QSTR_halt), MP_ROM_PTR(&mod_trezorutils_halt_obj)},
{MP_ROM_QSTR(MP_QSTR_firmware_hash),
MP_ROM_PTR(&mod_trezorutils_firmware_hash_obj)},
diff --git a/core/mocks/generated/trezorutils.pyi b/core/mocks/generated/trezorutils.pyi
index a368f57a4..3798ac5fe 100644
--- a/core/mocks/generated/trezorutils.pyi
+++ b/core/mocks/generated/trezorutils.pyi
@@ -34,6 +34,15 @@ def memcpy(
"""
+# upymod/modtrezorutils/modtrezorutils.c
+def memzero(
+ dst: bytearray | memoryview,
+) -> None:
+ """
+ Zeroes all bytes at `dst`.
+ """
+
+
# upymod/modtrezorutils/modtrezorutils.c
def halt(msg: str | None = None) -> None:
"""
diff --git a/core/src/trezor/utils.py b/core/src/trezor/utils.py
index 1b1b50484..fa1046374 100644
--- a/core/src/trezor/utils.py
+++ b/core/src/trezor/utils.py
@@ -29,6 +29,7 @@ from trezorutils import ( # noqa: F401
firmware_vendor,
halt,
memcpy,
+ memzero,
presize_module,
reboot_to_bootloader,
sd_hotswap_enabled,
diff --git a/core/tests/test_trezor.utils.py b/core/tests/test_trezor.utils.py
index 58838fdfa..c91fba151 100644
--- a/core/tests/test_trezor.utils.py
+++ b/core/tests/test_trezor.utils.py
@@ -76,6 +76,13 @@ class TestUtils(unittest.TestCase):
b"\xa0\x93@\x98\xa6\x80\xdb\x07m\xdf~\xe2'E\xf1\x19\xd8\xfd\xa4`\x10H\xf0_\xdbf\xa6N\xdd\xc0\xcf\xed",
)
+ def test_memzero(self):
+ data = bytearray(range(10))
+ utils.memzero(memoryview(data)[3:7])
+ self.assertEqual(data, bytearray([0, 1, 2, 0, 0, 0, 0, 7, 8, 9]))
+ utils.memzero(data)
+ self.assertEqual(data, bytearray(10))
+
if __name__ == "__main__":
unittest.main()
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.