chore(core): improve handling of large messages
What changed, and why it matters
This commit hardens how the Trezor firmware handles oversized messages in its low-level communication layer. Previously, asking for a buffer larger than the fixed 8 KB limit would trigger an internal assertion failure (a hard crash). Now the code returns a failure indicator and, in the sending path, raises a controlled FirmwareError instead. This is a defensive improvement that prevents a class of potential denial-of-service or crash conditions when very large messages are received or sent, but it does not by itself fix a known exploitable vulnerability.
Treat as a defensive hardening commit. Review whether callers of ThpBuffer.get() elsewhere handle None correctly, and consider whether the fixed 8192-byte buffer limit should be documented or made configurable. No urgent security response is indicated by the diff alone.
Security signals we found
Replaces an assert-based crash path with controlled failure handling for oversized buffers
Adds explicit None checks on buffer allocation in message reassembly and sending
Raises FirmwareError instead of allowing an assertion failure when a write buffer cannot be obtained
Removes duplicated constant, reducing maintenance risk
Evidence from the diff
The patch modifies the THP (Trezor Host Protocol) buffer manager so that ThpBuffer.get() returns None when the requested length exceeds _PROTOBUF_BUFFER_SIZE (8192 bytes), rather than asserting. Callers in channel.py’s Reassembler now check for None and abort reassembly cleanly. In Channel._send_message, a None write buffer now raises wire.FirmwareError. A duplicated CHECKSUM_LENGTH constant is also removed from writer.py. The change is therefore a robustness fix: it converts an assert-triggered crash path into a controlled failure path for messages that exceed the fixed buffer size.
Changed components
core/src/trezor/wire/thp/channel.pycore/src/trezor/wire/thp/memory_manager.pycore/src/trezor/wire/thp/writer.pyInspect captured patch +24 / −3
diff --git a/core/src/trezor/wire/thp/channel.py b/core/src/trezor/wire/thp/channel.py
index b7aa48be..38477f29 100644
--- a/core/src/trezor/wire/thp/channel.py
+++ b/core/src/trezor/wire/thp/channel.py
@@ -90,6 +90,9 @@ class Reassembler:
return False
buffer = self.thp_read_buf.get(self.buffer_len)
+ if buffer is None:
+ # Failed to get the buffer
+ return False
self._buffer_packet_data(buffer, packet, PacketHeader.CONT_LENGTH)
else:
self.reset()
@@ -97,6 +100,9 @@ class Reassembler:
self.buffer_len = payload_length + PacketHeader.INIT_LENGTH
buffer = self.thp_read_buf.get(self.buffer_len)
+ if buffer is None:
+ # Failed to get the buffer
+ return False
self._buffer_packet_data(buffer, packet, 0)
assert len(buffer) == self.buffer_len
@@ -415,6 +421,11 @@ class Channel:
length = payload_size + CHECKSUM_LENGTH + TAG_LENGTH + PacketHeader.INIT_LENGTH
buffer = self.write_buf.get(length)
+ if buffer is None:
+ from trezor import wire
+
+ raise wire.FirmwareError("Failed to get a sufficiently large write buffer.")
+
noise_payload_len = memory_manager.encode_into_buffer(buffer, msg, session_id)
self._encrypt(buffer, noise_payload_len)
diff --git a/core/src/trezor/wire/thp/memory_manager.py b/core/src/trezor/wire/thp/memory_manager.py
index 2235f629..bb6d2828 100644
--- a/core/src/trezor/wire/thp/memory_manager.py
+++ b/core/src/trezor/wire/thp/memory_manager.py
@@ -11,13 +11,24 @@ if TYPE_CHECKING:
_PROTOBUF_BUFFER_SIZE = const(8192)
+if __debug__:
+ from trezor import log
+
class ThpBuffer:
def __init__(self) -> None:
self.buf = memoryview(bytearray(_PROTOBUF_BUFFER_SIZE))
- def get(self, length: int) -> memoryview:
- assert length <= len(self.buf)
+ def get(self, length: int) -> memoryview | None:
+ assert length >= 0
+ if length > len(self.buf):
+ if __debug__:
+ log.warning(
+ __name__,
+ "Failed to get a buffer - requested length (%d) is too big.",
+ length,
+ )
+ return None
return self.buf[:length]
diff --git a/core/src/trezor/wire/thp/writer.py b/core/src/trezor/wire/thp/writer.py
index 7f13d61a..20316302 100644
--- a/core/src/trezor/wire/thp/writer.py
+++ b/core/src/trezor/wire/thp/writer.py
@@ -1,5 +1,4 @@
from micropython import const
-CHECKSUM_LENGTH = const(4)
MAX_PAYLOAD_LEN = const(60000)
MESSAGE_TYPE_LENGTH = const(2)
Why this scored 32/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.