Skip to content

Commit 6e45c37

Browse files
committed
fix(core): don't raise ThpError on low-level errors
`ThpError` ends up being sent over the protocol as `MessageType_Failure`, but in case of a low-level problem (e.g. retransimission timeout), it is probably not the correct thing to do. [no changelog]
1 parent 6a33e2d commit 6e45c37

File tree

5 files changed

+52
-37
lines changed

5 files changed

+52
-37
lines changed

core/src/trezor/wire/thp/alternating_bit_protocol.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from storage.cache_thp import ChannelCache
22

3-
from . import ThpError
4-
53

64
def is_ack_valid(cache: ChannelCache, ack_bit: int) -> bool:
75
"""
@@ -72,8 +70,7 @@ def set_expected_receive_seq_bit(cache: ChannelCache, seq_bit: int) -> None:
7270
Set the expected sequential number (bit) of the next message to be received
7371
in the provided channel
7472
"""
75-
if seq_bit not in (0, 1):
76-
raise ThpError("Unexpected receive sync bit")
73+
assert seq_bit in (0, 1)
7774

7875
# set second bit to "seq_bit" value
7976
cache.sync &= 0xBF
@@ -82,8 +79,7 @@ def set_expected_receive_seq_bit(cache: ChannelCache, seq_bit: int) -> None:
8279

8380

8481
def _set_send_seq_bit(cache: ChannelCache, seq_bit: int) -> None:
85-
if seq_bit not in (0, 1):
86-
raise ThpError("Unexpected send seq bit")
82+
assert seq_bit in (0, 1)
8783
# set third bit to "seq_bit" value
8884
cache.sync &= 0xDF
8985
if seq_bit:

core/src/trezor/wire/thp/channel.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,7 @@
2424
from trezor.loop import Timeout
2525

2626
from ..protocol_common import Message
27-
from . import (
28-
ACK_MESSAGE,
29-
ENCRYPTED,
30-
ChannelState,
31-
PacketHeader,
32-
ThpDecryptionError,
33-
ThpError,
34-
)
27+
from . import ACK_MESSAGE, ENCRYPTED, ChannelState, PacketHeader, ThpDecryptionError
3528
from . import alternating_bit_protocol as ABP
3629
from . import control_byte, crypto, memory_manager
3730
from .checksum import CHECKSUM_LENGTH, is_valid
@@ -102,7 +95,15 @@ def handle_packet(self, packet: memoryview) -> bool:
10295
return False
10396

10497
if self.bytes_read > self.buffer_len:
105-
raise ThpError("read more bytes than expected")
98+
if __debug__:
99+
log.warning(
100+
__name__,
101+
"Reassembled %d bytes, %d expected",
102+
self.bytes_read,
103+
self.buffer_len,
104+
)
105+
self.reset()
106+
return False
106107

107108
if not verify_checksum(buffer):
108109
return False
@@ -247,8 +248,12 @@ async def recv_payload(
247248

248249
if expected_ctrl_byte is None or not expected_ctrl_byte(ctrl_byte):
249250
if __debug__:
250-
self._log("Unexpected control byte: ", utils.hexlify_if_bytes(msg))
251-
raise ThpError("Unexpected control byte")
251+
self._log(
252+
"Unexpected control byte - ignoring ",
253+
utils.hexlify_if_bytes(msg),
254+
logger=log.warning,
255+
)
256+
continue
252257

253258
# 2: Handle message with unexpected sequential bit
254259
if seq_bit != ABP.get_expected_receive_seq_bit(self.channel_cache):
@@ -257,7 +262,7 @@ async def recv_payload(
257262
"Received message with an unexpected sequential bit",
258263
)
259264
await send_ack(self, ack_bit=seq_bit)
260-
raise ThpError("Received message with an unexpected sequential bit")
265+
continue
261266

262267
# 3: Send ACK in response
263268
await send_ack(self, ack_bit=seq_bit)
@@ -406,7 +411,7 @@ async def write_encrypted_payload(self, ctrl_byte: int, payload: bytes) -> None:
406411
ABP.set_send_seq_bit_to_opposite(self.channel_cache)
407412
return
408413

409-
raise ThpError("Retransmission timeout")
414+
raise Timeout("THP retransmission timeout")
410415

411416
def _encrypt(self, buffer: utils.BufferType, noise_payload_len: int) -> None:
412417
if __debug__:

core/src/trezor/wire/thp/control_byte.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
ENCRYPTED,
77
HANDSHAKE_COMP_REQ,
88
HANDSHAKE_INIT_REQ,
9-
ThpError,
109
)
1110

1211
_CONTINUATION_PACKET_MASK = const(0x80)
@@ -15,19 +14,19 @@
1514

1615

1716
def add_seq_bit_to_ctrl_byte(ctrl_byte: int, seq_bit: int) -> int:
18-
if seq_bit == 0:
19-
return ctrl_byte & 0xEF
20-
if seq_bit == 1:
17+
assert seq_bit in (0, 1)
18+
if seq_bit:
2119
return ctrl_byte | 0x10
22-
raise ThpError("Unexpected sequence bit")
20+
else:
21+
return ctrl_byte & 0xEF
2322

2423

2524
def add_ack_bit_to_ctrl_byte(ctrl_byte: int, ack_bit: int) -> int:
26-
if ack_bit == 0:
27-
return ctrl_byte & 0xF7
28-
if ack_bit == 1:
25+
assert ack_bit in (0, 1)
26+
if ack_bit:
2927
return ctrl_byte | 0x08
30-
raise ThpError("Unexpected acknowledgement bit")
28+
else:
29+
return ctrl_byte & 0xF7
3130

3231

3332
def get_ack_bit(ctrl_byte: int) -> int:

core/src/trezor/wire/thp/interface_context.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
CODEC_V1,
1616
PING,
1717
PacketHeader,
18-
ThpError,
1918
ThpErrorType,
2019
channel_manager,
2120
checksum,
@@ -126,10 +125,20 @@ async def _handle_broadcast(self, packet: bytes) -> None:
126125

127126
packet = packet[: PacketHeader.INIT_LENGTH + payload_length]
128127
if not checksum.is_valid(packet[-CHECKSUM_LENGTH:], packet[:-CHECKSUM_LENGTH]):
129-
raise ThpError("Invalid checksum")
128+
if __debug__:
129+
log.debug(
130+
__name__, "Invalid checksum: %s", utils.hexlify_if_bytes(packet)
131+
)
132+
return
130133

131134
if payload_length != _BROADCAST_PAYLOAD_LENGTH:
132-
raise ThpError("Invalid length in broadcast channel packet")
135+
if __debug__:
136+
log.debug(
137+
__name__,
138+
"Invalid length in broadcast channel packet: %d",
139+
payload_length,
140+
)
141+
return
133142

134143
nonce = packet[PacketHeader.INIT_LENGTH : -CHECKSUM_LENGTH]
135144

@@ -138,7 +147,13 @@ async def _handle_broadcast(self, packet: bytes) -> None:
138147
return await self.write_payload(response_header, nonce)
139148

140149
if ctrl_byte != CHANNEL_ALLOCATION_REQ:
141-
raise ThpError("Unexpected ctrl_byte in a broadcast channel packet")
150+
if __debug__:
151+
log.debug(
152+
__name__,
153+
"Unexpected ctrl_byte in a broadcast channel packet: %d",
154+
ctrl_byte,
155+
)
156+
return
142157

143158
channel_cache = channel_manager.create_new_channel(self._iface)
144159
response_data = get_channel_allocation_response(

core/src/trezor/wire/thp/received_message_handler.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
SessionState,
2222
ThpDecryptionError,
2323
ThpDeviceLockedError,
24-
ThpError,
2524
ThpErrorType,
2625
ThpUnallocatedSessionError,
2726
control_byte,
@@ -62,9 +61,9 @@ async def handle_received_message(channel: Channel) -> bool:
6261
elif state is ChannelState.TH1:
6362
await _handle_state_handshake(channel)
6463
return channel.get_channel_state() == ChannelState.TC1
65-
else:
66-
raise ThpError("Unimplemented channel state")
67-
64+
if __debug__:
65+
channel._log("Unimplemented channel state", logger=log.error)
66+
channel.clear()
6867
except ThpUnallocatedSessionError as e:
6968
error_message = Failure(code=FailureType.ThpUnallocatedSession)
7069
await channel.write(error_message, e.session_id)
@@ -89,7 +88,8 @@ async def _handle_state_handshake(
8988
payload = await ctx.recv_payload(control_byte.is_handshake_init_req)
9089

9190
if len(payload) != PUBKEY_LENGTH:
92-
raise ThpError("Message received is not a valid handshake init request!")
91+
log.error(__name__, "Message received is not a valid handshake init request!")
92+
return
9393

9494
if not config.is_unlocked():
9595
raise ThpDeviceLockedError

0 commit comments

Comments
 (0)