refactor(core): avoid `bytearray` allocation
What changed, and why it matters
This is a small internal code cleanup in Trezor firmware. It removes an unnecessary conversion of a byte slice into a mutable bytearray before storing it in a channel cache. The change is described by the developer as a memory-allocation optimization and is not presented as a security fix.
No security action required. Treat as a normal code-quality refactor. If reviewing, verify that downstream consumers of `DataCache.set()` still handle `memoryview` correctly (e.g., slicing behavior) and that the cache serialization path does not assume a mutable buffer.
Security signals we found
No security-relevant signal: change is a memory-allocation refactor in type annotations and one wrapper removal.
Length validation of the host static public key remains in place.
No changelog entry and commit title/message do not mention security.
Evidence from the diff
The commit changes DataCache.set() to accept bytes | memoryview, changes ChannelCache.set_host_static_public_key() to accept memoryview instead of bytearray, and updates the caller in received_message_handler.py to pass host_static_public_key directly instead of wrapping it with bytearray(). This avoids one heap allocation and a copy during the Tropic Square THP handshake. The public key is still length-checked before use. No security boundary is changed, no validation is removed, and no vulnerability is disclosed.
Changed components
core/src/storage/cache_common.pycore/src/storage/cache_thp.pycore/src/trezor/wire/thp/received_message_handler.pyInspect captured patch +3 / −3
diff --git a/core/src/storage/cache_common.py b/core/src/storage/cache_common.py
index 2cd0bbadf..dd87f5a0d 100644
--- a/core/src/storage/cache_common.py
+++ b/core/src/storage/cache_common.py
@@ -76,7 +76,7 @@ class DataCache:
utils.ensure(key < len(self.fields))
return self.data[key][0] == 1
- def set(self, key: int, value: bytes) -> None:
+ def set(self, key: int, value: bytes | memoryview) -> None:
utils.ensure(key < len(self.fields))
utils.ensure(len(value) <= self.fields[key])
self.data[key][0] = 1
diff --git a/core/src/storage/cache_thp.py b/core/src/storage/cache_thp.py
index 7247616ce..2af7db6ad 100644
--- a/core/src/storage/cache_thp.py
+++ b/core/src/storage/cache_thp.py
@@ -68,7 +68,7 @@ class ChannelCache(ThpDataCache):
def sync(self, value: int) -> None:
self.set_int(CHANNEL_SYNC, value)
- def set_host_static_public_key(self, key: bytearray) -> None:
+ def set_host_static_public_key(self, key: memoryview) -> None:
if len(key) != KEY_LENGTH:
raise ValueError("Invalid key length")
self.set(CHANNEL_HOST_STATIC_PUBKEY, key)
diff --git a/core/src/trezor/wire/thp/received_message_handler.py b/core/src/trezor/wire/thp/received_message_handler.py
index 0240c68cf..d4307a198 100644
--- a/core/src/trezor/wire/thp/received_message_handler.py
+++ b/core/src/trezor/wire/thp/received_message_handler.py
@@ -160,7 +160,7 @@ async def _handle_state_handshake(
# key is decoded in handshake._handle_th2_crypto
host_static_public_key = host_encrypted_static_public_key[:PUBKEY_LENGTH]
- ctx.channel_cache.set_host_static_public_key(bytearray(host_static_public_key))
+ ctx.channel_cache.set_host_static_public_key(host_static_public_key)
paired: bool = False
trezor_state = _TREZOR_STATE_UNPAIRED
Why this scored 17/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.