1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-03 03:50:58 +00:00

wip - change session behavior

[no changelog]
This commit is contained in:
M1nd3r 2024-12-09 16:08:30 +01:00
parent cdb96f4521
commit 0c353eb242
14 changed files with 201 additions and 212 deletions

View File

@ -78,7 +78,6 @@ message ThpCreateNewSession{
optional string passphrase = 1; optional string passphrase = 1;
optional bool on_device = 2; // User wants to enter passphrase on the device optional bool on_device = 2; // User wants to enter passphrase on the device
optional bool derive_cardano = 3; // If True, Cardano keys will be derived. Ignored with BTC-only optional bool derive_cardano = 3; // If True, Cardano keys will be derived. Ignored with BTC-only
optional uint32 session_id = 4; // Id of the session to modify
} }
/** /**

View File

@ -220,13 +220,15 @@ if utils.USE_THP:
""" """
from trezor import log, loop from trezor import log, loop
from trezor.enums import FailureType from trezor.enums import FailureType
from trezor.messages import Failure, ThpNewSession from trezor.messages import Failure
from trezor.wire import NotInitialized from trezor.wire import NotInitialized
from trezor.wire.context import get_context from trezor.wire.context import get_context
from trezor.wire.errors import ActionCancelled, DataError from trezor.wire.errors import ActionCancelled, DataError
from trezor.wire.thp import SessionState
from trezor.wire.thp.session_context import GenericSessionContext from trezor.wire.thp.session_context import GenericSessionContext
from trezor.wire.thp.session_manager import create_new_session from trezor.wire.thp.session_manager import (
get_new_management_session_ctx,
get_new_session_context,
)
from apps.common.seed import derive_and_store_roots from apps.common.seed import derive_and_store_roots
@ -236,11 +238,38 @@ if utils.USE_THP:
assert isinstance(ctx, GenericSessionContext) assert isinstance(ctx, GenericSessionContext)
channel = ctx.channel channel = ctx.channel
session_id = ctx.session_id
# Do not use `ctx` beyond this point, as it is techically # Do not use `ctx` beyond this point, as it is techically
# allowed to change in between await statements # allowed to change in between await statements
if message.session_id is None:
new_session = create_new_session(channel) is_management = (
message.passphrase is None
and message.on_device is not True
and message.derive_cardano is not True
)
if not 0 <= session_id <= 255:
return Failure(
code=FailureType.DataError,
message="Invalid session_id for session creation.",
)
if is_management:
# TODO this block is completely useless and will be removed - or will result in session.clear
new_session = get_new_management_session_ctx(
channel_ctx=channel, session_id=session_id
)
succ_message = "New management session created."
if __debug__ and utils.ALLOW_DEBUG_MESSAGES:
log.debug(
__name__, "New management session with sid %d created.", session_id
)
else:
new_session = get_new_session_context(
channel_ctx=channel, session_id=session_id
)
try: try:
await unlock_device() await unlock_device()
await derive_and_store_roots(new_session, message) await derive_and_store_roots(new_session, message)
@ -252,23 +281,20 @@ if utils.USE_THP:
return Failure(code=FailureType.NotInitialized, message=e.message) return Failure(code=FailureType.NotInitialized, message=e.message)
# TODO handle other errors (`Exception` when "Cardano icarus secret is already set!") # TODO handle other errors (`Exception` when "Cardano icarus secret is already set!")
new_session.set_session_state(SessionState.ALLOCATED) succ_message = "New session created."
channel.sessions[new_session.session_id] = new_session
loop.schedule(new_session.handle())
new_session_id: int = new_session.session_id
else:
# HMMMMMMMMMMMMMMMMMM
pass
if __debug__ and utils.ALLOW_DEBUG_MESSAGES:
log.debug(
__name__,
"create_new_session - new session created. Passphrase: %s, Session id: %d\n%s",
message.passphrase if message.passphrase is not None else "",
new_session.session_id,
str(channel.sessions),
)
return ThpNewSession(new_session_id=new_session_id) if __debug__ and utils.ALLOW_DEBUG_MESSAGES:
log.debug(
__name__,
"New session with sid %d and passphrase %s created.",
session_id,
message.passphrase if message.passphrase is not None else "",
)
channel.sessions[new_session.session_id] = new_session
loop.schedule(new_session.handle())
return Success(message=succ_message)
else: else:

View File

@ -24,7 +24,8 @@ BROADCAST_CHANNEL_ID = const(0xFFFF)
KEY_LENGTH = const(32) KEY_LENGTH = const(32)
TAG_LENGTH = const(16) TAG_LENGTH = const(16)
_UNALLOCATED_STATE = const(0) _UNALLOCATED_STATE = const(0)
_MANAGEMENT_STATE = const(2) _ALLOCATED_STATE = const(1)
_SEEDLESS_STATE = const(2)
MANAGEMENT_SESSION_ID = const(0) MANAGEMENT_SESSION_ID = const(0)
@ -176,28 +177,35 @@ def get_all_allocated_channels() -> list[ChannelCache]:
def get_allocated_session( def get_allocated_session(
channel_id: bytes, session_id: bytes channel_id: bytes, session_id: bytes
) -> SessionThpCache | None: ) -> SessionThpCache | None:
index = get_allocated_session_index(channel_id, session_id)
if index is None:
return index
return _SESSIONS[index]
def get_allocated_session_index(channel_id: bytes, session_id: bytes) -> int | None:
""" """
Finds and returns the first allocated session matching the given `channel_id` and `session_id`, Finds and returns index of the first allocated session matching the given `channel_id`
or `None` if no match is found. and `session_id`, or `None` if no match is found.
Raises `Exception` if either channel_id or session_id has an invalid length. Raises `Exception` if either channel_id or session_id has an invalid length.
""" """
if len(channel_id) != _CHANNEL_ID_LENGTH or len(session_id) != SESSION_ID_LENGTH: if len(channel_id) != _CHANNEL_ID_LENGTH or len(session_id) != SESSION_ID_LENGTH:
raise Exception("At least one of arguments has invalid length") raise Exception("At least one of arguments has invalid length")
for session in _SESSIONS: for i in range(_MAX_SESSIONS_COUNT):
if _get_session_state(session) == _UNALLOCATED_STATE: if _get_session_state(_SESSIONS[i]) == _UNALLOCATED_STATE:
continue continue
if session.channel_id != channel_id: if _SESSIONS[i].channel_id != channel_id:
continue continue
if session.session_id != session_id: if _SESSIONS[i].session_id != session_id:
continue continue
return session return i
return None return None
def is_management_session(session_cache: SessionThpCache) -> bool: def is_management_session(session_cache: SessionThpCache) -> bool:
return _get_session_state(session_cache) == _MANAGEMENT_STATE return _get_session_state(session_cache) == _SEEDLESS_STATE
def set_channel_host_ephemeral_key(channel: ChannelCache, key: bytearray) -> None: def set_channel_host_ephemeral_key(channel: ChannelCache, key: bytearray) -> None:
@ -206,26 +214,24 @@ def set_channel_host_ephemeral_key(channel: ChannelCache, key: bytearray) -> Non
channel.host_ephemeral_pubkey = key channel.host_ephemeral_pubkey = key
def get_new_session(channel: ChannelCache, management: bool = False) -> SessionThpCache: def create_or_replace_session(
new_sid = get_next_session_id(channel) channel: ChannelCache, session_id: bytes
index = _get_next_session_index() ) -> SessionThpCache:
index = get_allocated_session_index(channel.channel_id, session_id)
if index is None:
index = _get_next_session_index()
_SESSIONS[index] = SessionThpCache() _SESSIONS[index] = SessionThpCache()
_SESSIONS[index].channel_id[:] = channel.channel_id _SESSIONS[index].channel_id[:] = channel.channel_id
_SESSIONS[index].session_id[:] = new_sid _SESSIONS[index].session_id[:] = session_id
_SESSIONS[index].last_usage = _get_usage_counter_and_increment() _SESSIONS[index].last_usage = _get_usage_counter_and_increment()
channel.last_usage = ( channel.last_usage = (
_get_usage_counter_and_increment() _get_usage_counter_and_increment()
) # increment also use of the channel so it does not get replaced ) # increment also use of the channel so it does not get replaced
if management: _SESSIONS[index].state[:] = bytearray(
_SESSIONS[index].state[:] = bytearray( _ALLOCATED_STATE.to_bytes(_SESSION_STATE_LENGTH, "big")
_MANAGEMENT_STATE.to_bytes(_SESSION_STATE_LENGTH, "big") )
)
else:
_SESSIONS[index].state[:] = bytearray(
_UNALLOCATED_STATE.to_bytes(_SESSION_STATE_LENGTH, "big")
)
return _SESSIONS[index] return _SESSIONS[index]
@ -239,14 +245,14 @@ def _get_next_channel_index() -> int:
idx = _get_unallocated_channel_index() idx = _get_unallocated_channel_index()
if idx is not None: if idx is not None:
return idx return idx
return get_least_recently_used_item(_CHANNELS, max_count=_MAX_CHANNELS_COUNT) return _get_least_recently_used_item(_CHANNELS, max_count=_MAX_CHANNELS_COUNT)
def _get_next_session_index() -> int: def _get_next_session_index() -> int:
idx = _get_unallocated_session_index() idx = _get_unallocated_session_index()
if idx is not None: if idx is not None:
return idx return idx
return get_least_recently_used_item(_SESSIONS, max_count=_MAX_SESSIONS_COUNT) return _get_least_recently_used_item(_SESSIONS, max_count=_MAX_SESSIONS_COUNT)
def _get_unallocated_channel_index() -> int | None: def _get_unallocated_channel_index() -> int | None:
@ -282,19 +288,19 @@ def get_next_channel_id() -> bytes:
return cid_counter.to_bytes(_CHANNEL_ID_LENGTH, "big") return cid_counter.to_bytes(_CHANNEL_ID_LENGTH, "big")
def get_next_session_id(channel: ChannelCache) -> bytes: def _deprecated_get_next_session_id(channel: ChannelCache) -> bytes:
while True: while True:
if channel.session_id_counter >= 255: if channel.session_id_counter >= 255:
channel.session_id_counter = 1 channel.session_id_counter = 1
else: else:
channel.session_id_counter += 1 channel.session_id_counter += 1
if _is_session_id_unique(channel): if _deprecated_is_session_id_unique(channel):
break break
new_sid = channel.session_id_counter new_sid = channel.session_id_counter
return new_sid.to_bytes(SESSION_ID_LENGTH, "big") return new_sid.to_bytes(SESSION_ID_LENGTH, "big")
def _is_session_id_unique(channel: ChannelCache) -> bool: def _deprecated_is_session_id_unique(channel: ChannelCache) -> bool:
for session in _SESSIONS: for session in _SESSIONS:
if session.channel_id == channel.channel_id: if session.channel_id == channel.channel_id:
if session.session_id == channel.session_id_counter: if session.session_id == channel.session_id_counter:
@ -311,7 +317,7 @@ def _is_cid_unique() -> bool:
return True return True
def get_least_recently_used_item( def _get_least_recently_used_item(
list: list[ChannelCache] | list[SessionThpCache], max_count: int list: list[ChannelCache] | list[SessionThpCache], max_count: int
) -> int: ) -> int:
global _usage_counter global _usage_counter
@ -366,6 +372,6 @@ def clear_all_except_one_session_keys(excluded: Tuple[bytes, bytes]) -> None:
s_last_usage = session.last_usage s_last_usage = session.last_usage
session.clear() session.clear()
session.last_usage = s_last_usage session.last_usage = s_last_usage
session.state = bytearray(_MANAGEMENT_STATE.to_bytes(1, "big")) session.state = bytearray(_SEEDLESS_STATE.to_bytes(1, "big"))
session.session_id[:] = bytearray(sid) session.session_id[:] = bytearray(sid)
session.channel_id[:] = bytearray(cid) session.channel_id[:] = bytearray(cid)

View File

@ -6182,7 +6182,6 @@ if TYPE_CHECKING:
passphrase: "str | None" passphrase: "str | None"
on_device: "bool | None" on_device: "bool | None"
derive_cardano: "bool | None" derive_cardano: "bool | None"
session_id: "int | None"
def __init__( def __init__(
self, self,
@ -6190,7 +6189,6 @@ if TYPE_CHECKING:
passphrase: "str | None" = None, passphrase: "str | None" = None,
on_device: "bool | None" = None, on_device: "bool | None" = None,
derive_cardano: "bool | None" = None, derive_cardano: "bool | None" = None,
session_id: "int | None" = None,
) -> None: ) -> None:
pass pass

View File

@ -72,7 +72,7 @@ class ChannelState(IntEnum):
class SessionState(IntEnum): class SessionState(IntEnum):
UNALLOCATED = 0 UNALLOCATED = 0
ALLOCATED = 1 ALLOCATED = 1
MANAGEMENT = 2 SEEDLESS = 2
class PacketHeader: class PacketHeader:

View File

@ -23,9 +23,9 @@ from . import (
from .checksum import CHECKSUM_LENGTH from .checksum import CHECKSUM_LENGTH
from .transmission_loop import TransmissionLoop from .transmission_loop import TransmissionLoop
from .writer import ( from .writer import (
PACKET_LENGTH,
CONT_HEADER_LENGTH, CONT_HEADER_LENGTH,
INIT_HEADER_LENGTH, INIT_HEADER_LENGTH,
PACKET_LENGTH,
write_payload_to_wire_and_add_checksum, write_payload_to_wire_and_add_checksum,
) )

View File

@ -10,7 +10,6 @@ from storage.cache_common import (
) )
from storage.cache_thp import ( from storage.cache_thp import (
KEY_LENGTH, KEY_LENGTH,
MANAGEMENT_SESSION_ID,
SESSION_ID_LENGTH, SESSION_ID_LENGTH,
TAG_LENGTH, TAG_LENGTH,
update_channel_last_used, update_channel_last_used,
@ -46,6 +45,7 @@ from . import (
) )
from .checksum import CHECKSUM_LENGTH from .checksum import CHECKSUM_LENGTH
from .crypto import PUBKEY_LENGTH, Handshake from .crypto import PUBKEY_LENGTH, Handshake
from .session_context import SeedlessSessionContext
from .writer import ( from .writer import (
INIT_HEADER_LENGTH, INIT_HEADER_LENGTH,
MESSAGE_TYPE_LENGTH, MESSAGE_TYPE_LENGTH,
@ -353,23 +353,18 @@ async def _handle_state_ENCRYPTED_TRANSPORT(ctx: Channel, message_length: int) -
">BH", memoryview(ctx.buffer)[INIT_HEADER_LENGTH:] ">BH", memoryview(ctx.buffer)[INIT_HEADER_LENGTH:]
) )
if session_id not in ctx.sessions: if session_id not in ctx.sessions:
if session_id == MANAGEMENT_SESSION_ID:
s = session_manager.create_new_management_session(ctx) s = session_manager.get_session_from_cache(ctx, session_id)
else:
s = session_manager.get_session_from_cache(ctx, session_id)
if s is None: if s is None:
assert session_id != MANAGEMENT_SESSION_ID s = SeedlessSessionContext(ctx, session_id)
# Create management session backed by cache (non-trivial session_id)
s = session_manager.create_new_management_session(ctx, session_id)
ctx.sessions[session_id] = s ctx.sessions[session_id] = s
loop.schedule(s.handle()) loop.schedule(s.handle())
elif ctx.sessions[session_id].get_session_state() is SessionState.UNALLOCATED: elif ctx.sessions[session_id].get_session_state() is SessionState.UNALLOCATED:
raise ThpUnallocatedSessionError(session_id) raise ThpUnallocatedSessionError(session_id)
# TODO what should happen here? Should I create a new management session? # TODO what should happen here? Should I create a new seedless session?
s = ctx.sessions[session_id] s = ctx.sessions[session_id]
update_session_last_used(s.channel_id, (s.session_id).to_bytes(1, "big")) update_session_last_used(s.channel_id, (s.session_id).to_bytes(1, "big"))

View File

@ -1,7 +1,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from storage import cache_thp from storage import cache_thp
from storage.cache_thp import MANAGEMENT_SESSION_ID, SessionThpCache from storage.cache_thp import SessionThpCache
from trezor import log, loop, protobuf, utils from trezor import log, loop, protobuf, utils
from trezor.wire import message_handler, protocol_common from trezor.wire import message_handler, protocol_common
from trezor.wire.context import UnexpectedMessageException from trezor.wire.context import UnexpectedMessageException
@ -128,23 +128,13 @@ class GenericSessionContext(Context):
def get_session_state(self) -> SessionState: ... def get_session_state(self) -> SessionState: ...
class ManagementSessionContext(GenericSessionContext): class SeedlessSessionContext(GenericSessionContext):
def __init__( def __init__(self, channel_ctx: Channel, session_id: int) -> None:
self,
channel_ctx: Channel,
session_id: int = MANAGEMENT_SESSION_ID,
session_cache: SessionThpCache | None = None,
) -> None:
self.session_cache = session_cache
super().__init__(channel_ctx, session_id) super().__init__(channel_ctx, session_id)
def get_session_state(self) -> SessionState: def get_session_state(self) -> SessionState:
return SessionState.MANAGEMENT return SessionState.SEEDLESS
def release(self) -> None:
if self.session_cache is not None:
cache_thp.clear_session(self.session_cache)
class SessionContext(GenericSessionContext): class SessionContext(GenericSessionContext):

View File

@ -4,7 +4,7 @@ from storage import cache_thp
from .session_context import ( from .session_context import (
GenericSessionContext, GenericSessionContext,
ManagementSessionContext, SeedlessSessionContext,
SessionContext, SessionContext,
) )
@ -12,25 +12,26 @@ if TYPE_CHECKING:
from .channel import Channel from .channel import Channel
def create_new_session(channel_ctx: Channel) -> SessionContext: def get_new_session_context(
""" channel_ctx: Channel,
Creates new `SessionContext` backed by cache. session_id: int,
""" ) -> SessionContext:
session_cache = cache_thp.get_new_session(channel_ctx.channel_cache) session_cache = cache_thp.create_or_replace_session(
channel=channel_ctx.channel_cache,
session_id=session_id.to_bytes(1, "big"),
)
return SessionContext(channel_ctx, session_cache) return SessionContext(channel_ctx, session_cache)
def create_new_management_session( def get_new_management_session_ctx(
channel_ctx: Channel, session_id: int = cache_thp.MANAGEMENT_SESSION_ID channel_ctx: Channel, session_id: int
) -> ManagementSessionContext: ) -> SeedlessSessionContext:
""" """
Creates new `ManagementSessionContext` that is not backed by cache entry. Creates new `ManagementSessionContext` that is not backed by a cache entry.
Seed cannot be derived with this type of session. Seed cannot be derived with this type of session.
""" """
if session_id != cache_thp.MANAGEMENT_SESSION_ID: return SeedlessSessionContext(channel_ctx, session_id)
cache_thp.get_new_session(channel_ctx.channel_cache, management=True)
return ManagementSessionContext(channel_ctx, session_id)
def get_session_from_cache( def get_session_from_cache(
@ -46,5 +47,5 @@ def get_session_from_cache(
if session_cache is None: if session_cache is None:
return None return None
elif cache_thp.is_management_session(session_cache): elif cache_thp.is_management_session(session_cache):
return ManagementSessionContext(channel_ctx, session_id) return SeedlessSessionContext(channel_ctx, session_id)
return SessionContext(channel_ctx, session_cache) return SessionContext(channel_ctx, session_cache)

View File

@ -48,11 +48,15 @@ class TestStorageCache(unittest.TestCase):
self.assertEqual(len(channel.sessions), 0) self.assertEqual(len(channel.sessions), 0)
cid_1 = channel.channel_id cid_1 = channel.channel_id
session_cache_1 = cache_thp.get_new_session(channel.channel_cache) session_cache_1 = cache_thp._deprecated_get_new_session(
channel.channel_cache
)
session_1 = SessionContext(channel, session_cache_1) session_1 = SessionContext(channel, session_cache_1)
self.assertEqual(session_1.channel_id, cid_1) self.assertEqual(session_1.channel_id, cid_1)
session_cache_2 = cache_thp.get_new_session(channel.channel_cache) session_cache_2 = cache_thp._deprecated_get_new_session(
channel.channel_cache
)
session_2 = SessionContext(channel, session_cache_2) session_2 = SessionContext(channel, session_cache_2)
self.assertEqual(session_2.channel_id, cid_1) self.assertEqual(session_2.channel_id, cid_1)
self.assertEqual(session_1.channel_id, session_2.channel_id) self.assertEqual(session_1.channel_id, session_2.channel_id)
@ -62,7 +66,9 @@ class TestStorageCache(unittest.TestCase):
cid_2 = channel_2.channel_id cid_2 = channel_2.channel_id
self.assertNotEqual(cid_1, cid_2) self.assertNotEqual(cid_1, cid_2)
session_cache_3 = cache_thp.get_new_session(channel_2.channel_cache) session_cache_3 = cache_thp._deprecated_get_new_session(
channel_2.channel_cache
)
session_3 = SessionContext(channel_2, session_cache_3) session_3 = SessionContext(channel_2, session_cache_3)
self.assertEqual(session_3.channel_id, cid_2) self.assertEqual(session_3.channel_id, cid_2)
@ -136,13 +142,15 @@ class TestStorageCache(unittest.TestCase):
cid = [] cid = []
sid = [] sid = []
for i in range(3): for i in range(3):
sesions_A.append(cache_thp.get_new_session(channel_cache_A)) sesions_A.append(cache_thp._deprecated_get_new_session(channel_cache_A))
cid.append(sesions_A[i].channel_id) cid.append(sesions_A[i].channel_id)
sid.append(sesions_A[i].session_id) sid.append(sesions_A[i].session_id)
sessions_B = [] sessions_B = []
for i in range(cache_thp._MAX_SESSIONS_COUNT - 3): for i in range(cache_thp._MAX_SESSIONS_COUNT - 3):
sessions_B.append(cache_thp.get_new_session(channel_cache_B)) sessions_B.append(
cache_thp._deprecated_get_new_session(channel_cache_B)
)
for i in range(3): for i in range(3):
self.assertEqual(sesions_A[i], cache_thp._SESSIONS[i]) self.assertEqual(sesions_A[i], cache_thp._SESSIONS[i])
@ -152,7 +160,7 @@ class TestStorageCache(unittest.TestCase):
self.assertEqual(sessions_B[i - 3], cache_thp._SESSIONS[i]) self.assertEqual(sessions_B[i - 3], cache_thp._SESSIONS[i])
# Assert that new session replaces the oldest (least used) one (_SESSOIONS[0]) # Assert that new session replaces the oldest (least used) one (_SESSOIONS[0])
new_session = cache_thp.get_new_session(channel_cache_B) new_session = cache_thp._deprecated_get_new_session(channel_cache_B)
self.assertEqual(new_session, cache_thp._SESSIONS[0]) self.assertEqual(new_session, cache_thp._SESSIONS[0])
self.assertNotEqual(new_session.channel_id, cid[0]) self.assertNotEqual(new_session.channel_id, cid[0])
self.assertNotEqual(new_session.session_id, sid[0]) self.assertNotEqual(new_session.session_id, sid[0])
@ -165,7 +173,7 @@ class TestStorageCache(unittest.TestCase):
) )
self.assertTrue(channel_cache_A.last_usage > channel_cache_B.last_usage) self.assertTrue(channel_cache_A.last_usage > channel_cache_B.last_usage)
new_new_session = cache_thp.get_new_session(channel_cache_B) new_new_session = cache_thp._deprecated_get_new_session(channel_cache_B)
# Assert that creating a new session on channel B shifts the "last usage" again # Assert that creating a new session on channel B shifts the "last usage" again
# and that _SESSIONS[1] was not replaced, but that _SESSIONS[2] was replaced # and that _SESSIONS[1] was not replaced, but that _SESSIONS[2] was replaced
@ -182,8 +190,12 @@ class TestStorageCache(unittest.TestCase):
sessions = [] sessions = []
for i in range(3): for i in range(3):
sessions.append(cache_thp.get_new_session(channel_A.channel_cache)) sessions.append(
sessions.append(cache_thp.get_new_session(channel_B.channel_cache)) cache_thp._deprecated_get_new_session(channel_A.channel_cache)
)
sessions.append(
cache_thp._deprecated_get_new_session(channel_B.channel_cache)
)
self.assertEqual(cache_thp._SESSIONS[2 * i].channel_id, cid_A) self.assertEqual(cache_thp._SESSIONS[2 * i].channel_id, cid_A)
self.assertNotEqual(cache_thp._SESSIONS[2 * i].last_usage, 0) self.assertNotEqual(cache_thp._SESSIONS[2 * i].last_usage, 0)
@ -224,11 +236,11 @@ class TestStorageCache(unittest.TestCase):
def test_get_set(self): def test_get_set(self):
channel = thp_common.get_new_channel(self.interface) channel = thp_common.get_new_channel(self.interface)
session_1 = cache_thp.get_new_session(channel.channel_cache) session_1 = cache_thp._deprecated_get_new_session(channel.channel_cache)
session_1.set(KEY, b"hello") session_1.set(KEY, b"hello")
self.assertEqual(session_1.get(KEY), b"hello") self.assertEqual(session_1.get(KEY), b"hello")
session_2 = cache_thp.get_new_session(channel.channel_cache) session_2 = cache_thp._deprecated_get_new_session(channel.channel_cache)
session_2.set(KEY, b"world") session_2.set(KEY, b"world")
self.assertEqual(session_2.get(KEY), b"world") self.assertEqual(session_2.get(KEY), b"world")
@ -241,12 +253,12 @@ class TestStorageCache(unittest.TestCase):
def test_get_set_int(self): def test_get_set_int(self):
channel = thp_common.get_new_channel(self.interface) channel = thp_common.get_new_channel(self.interface)
session_1 = cache_thp.get_new_session(channel.channel_cache) session_1 = cache_thp._deprecated_get_new_session(channel.channel_cache)
session_1.set_int(KEY, 1234) session_1.set_int(KEY, 1234)
self.assertEqual(session_1.get_int(KEY), 1234) self.assertEqual(session_1.get_int(KEY), 1234)
session_2 = cache_thp.get_new_session(channel.channel_cache) session_2 = cache_thp._deprecated_get_new_session(channel.channel_cache)
session_2.set_int(KEY, 5678) session_2.set_int(KEY, 5678)
self.assertEqual(session_2.get_int(KEY), 5678) self.assertEqual(session_2.get_int(KEY), 5678)
@ -259,7 +271,7 @@ class TestStorageCache(unittest.TestCase):
def test_get_set_bool(self): def test_get_set_bool(self):
channel = thp_common.get_new_channel(self.interface) channel = thp_common.get_new_channel(self.interface)
session_1 = cache_thp.get_new_session(channel.channel_cache) session_1 = cache_thp._deprecated_get_new_session(channel.channel_cache)
with self.assertRaises(AssertionError): with self.assertRaises(AssertionError):
session_1.set_bool(KEY, True) session_1.set_bool(KEY, True)
@ -270,7 +282,7 @@ class TestStorageCache(unittest.TestCase):
session_1.set_bool(KEY, True) session_1.set_bool(KEY, True)
self.assertEqual(session_1.get_bool(KEY), True) self.assertEqual(session_1.get_bool(KEY), True)
session_2 = cache_thp.get_new_session(channel.channel_cache) session_2 = cache_thp._deprecated_get_new_session(channel.channel_cache)
session_2.fields = session_2.fields = (0,) + session_2.fields[1:] session_2.fields = session_2.fields = (0,) + session_2.fields[1:]
session_2.set_bool(KEY, False) session_2.set_bool(KEY, False)
self.assertEqual(session_2.get_bool(KEY), False) self.assertEqual(session_2.get_bool(KEY), False)
@ -285,7 +297,7 @@ class TestStorageCache(unittest.TestCase):
def test_delete(self): def test_delete(self):
channel = thp_common.get_new_channel(self.interface) channel = thp_common.get_new_channel(self.interface)
session_1 = cache_thp.get_new_session(channel.channel_cache) session_1 = cache_thp._deprecated_get_new_session(channel.channel_cache)
self.assertIsNone(session_1.get(KEY)) self.assertIsNone(session_1.get(KEY))
session_1.set(KEY, b"hello") session_1.set(KEY, b"hello")
@ -294,7 +306,7 @@ class TestStorageCache(unittest.TestCase):
self.assertIsNone(session_1.get(KEY)) self.assertIsNone(session_1.get(KEY))
session_1.set(KEY, b"hello") session_1.set(KEY, b"hello")
session_2 = cache_thp.get_new_session(channel.channel_cache) session_2 = cache_thp._deprecated_get_new_session(channel.channel_cache)
self.assertIsNone(session_2.get(KEY)) self.assertIsNone(session_2.get(KEY))
session_2.set(KEY, b"hello") session_2.set(KEY, b"hello")

View File

@ -31,7 +31,7 @@ if utils.USE_THP:
def prepare_context() -> None: def prepare_context() -> None:
channel = get_new_channel() channel = get_new_channel()
session_cache = cache_thp.get_new_session(channel.channel_cache) session_cache = cache_thp._deprecated_get_new_session(channel.channel_cache)
session_ctx = SessionContext(channel, session_cache) session_ctx = SessionContext(channel, session_cache)
context.CURRENT_CONTEXT = session_ctx context.CURRENT_CONTEXT = session_ctx

View File

@ -7915,7 +7915,6 @@ class ThpCreateNewSession(protobuf.MessageType):
1: protobuf.Field("passphrase", "string", repeated=False, required=False, default=None), 1: protobuf.Field("passphrase", "string", repeated=False, required=False, default=None),
2: protobuf.Field("on_device", "bool", repeated=False, required=False, default=None), 2: protobuf.Field("on_device", "bool", repeated=False, required=False, default=None),
3: protobuf.Field("derive_cardano", "bool", repeated=False, required=False, default=None), 3: protobuf.Field("derive_cardano", "bool", repeated=False, required=False, default=None),
4: protobuf.Field("session_id", "uint32", repeated=False, required=False, default=None),
} }
def __init__( def __init__(
@ -7924,12 +7923,10 @@ class ThpCreateNewSession(protobuf.MessageType):
passphrase: Optional["str"] = None, passphrase: Optional["str"] = None,
on_device: Optional["bool"] = None, on_device: Optional["bool"] = None,
derive_cardano: Optional["bool"] = None, derive_cardano: Optional["bool"] = None,
session_id: Optional["int"] = None,
) -> None: ) -> None:
self.passphrase = passphrase self.passphrase = passphrase
self.on_device = on_device self.on_device = on_device
self.derive_cardano = derive_cardano self.derive_cardano = derive_cardano
self.session_id = session_id
class ThpNewSession(protobuf.MessageType): class ThpNewSession(protobuf.MessageType):

View File

@ -174,17 +174,19 @@ class SessionV2(Session):
@classmethod @classmethod
def new( def new(
cls, client: TrezorClient, passphrase: str | None, derive_cardano: bool cls,
client: TrezorClient,
passphrase: str | None,
derive_cardano: bool,
session_id: int = 0,
) -> SessionV2: ) -> SessionV2:
assert isinstance(client.protocol, ProtocolV2) assert isinstance(client.protocol, ProtocolV2)
session = cls(client, b"\x00") session = cls(client, session_id.to_bytes(1, "big"))
new_session: messages.ThpNewSession = session.call( _: messages.Success = session.call(
messages.ThpCreateNewSession( messages.ThpCreateNewSession(
passphrase=passphrase, derive_cardano=derive_cardano passphrase=passphrase, derive_cardano=derive_cardano
) )
) )
assert new_session.new_session_id is not None
session_id = new_session.new_session_id
session.update_id_and_sid(session_id.to_bytes(1, "big")) session.update_id_and_sid(session_id.to_bytes(1, "big"))
return session return session

View File

@ -504,8 +504,6 @@ pub struct ThpCreateNewSession {
pub on_device: ::std::option::Option<bool>, pub on_device: ::std::option::Option<bool>,
// @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCreateNewSession.derive_cardano) // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCreateNewSession.derive_cardano)
pub derive_cardano: ::std::option::Option<bool>, pub derive_cardano: ::std::option::Option<bool>,
// @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCreateNewSession.session_id)
pub session_id: ::std::option::Option<u32>,
// special fields // special fields
// @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpCreateNewSession.special_fields) // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpCreateNewSession.special_fields)
pub special_fields: ::protobuf::SpecialFields, pub special_fields: ::protobuf::SpecialFields,
@ -596,27 +594,8 @@ impl ThpCreateNewSession {
self.derive_cardano = ::std::option::Option::Some(v); self.derive_cardano = ::std::option::Option::Some(v);
} }
// optional uint32 session_id = 4;
pub fn session_id(&self) -> u32 {
self.session_id.unwrap_or(0)
}
pub fn clear_session_id(&mut self) {
self.session_id = ::std::option::Option::None;
}
pub fn has_session_id(&self) -> bool {
self.session_id.is_some()
}
// Param is passed by value, moved
pub fn set_session_id(&mut self, v: u32) {
self.session_id = ::std::option::Option::Some(v);
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(4); let mut fields = ::std::vec::Vec::with_capacity(3);
let mut oneofs = ::std::vec::Vec::with_capacity(0); let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"passphrase", "passphrase",
@ -633,11 +612,6 @@ impl ThpCreateNewSession {
|m: &ThpCreateNewSession| { &m.derive_cardano }, |m: &ThpCreateNewSession| { &m.derive_cardano },
|m: &mut ThpCreateNewSession| { &mut m.derive_cardano }, |m: &mut ThpCreateNewSession| { &mut m.derive_cardano },
)); ));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"session_id",
|m: &ThpCreateNewSession| { &m.session_id },
|m: &mut ThpCreateNewSession| { &mut m.session_id },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<ThpCreateNewSession>( ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<ThpCreateNewSession>(
"ThpCreateNewSession", "ThpCreateNewSession",
fields, fields,
@ -665,9 +639,6 @@ impl ::protobuf::Message for ThpCreateNewSession {
24 => { 24 => {
self.derive_cardano = ::std::option::Option::Some(is.read_bool()?); self.derive_cardano = ::std::option::Option::Some(is.read_bool()?);
}, },
32 => {
self.session_id = ::std::option::Option::Some(is.read_uint32()?);
},
tag => { tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
}, },
@ -689,9 +660,6 @@ impl ::protobuf::Message for ThpCreateNewSession {
if let Some(v) = self.derive_cardano { if let Some(v) = self.derive_cardano {
my_size += 1 + 1; my_size += 1 + 1;
} }
if let Some(v) = self.session_id {
my_size += ::protobuf::rt::uint32_size(4, v);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32); self.special_fields.cached_size().set(my_size as u32);
my_size my_size
@ -707,9 +675,6 @@ impl ::protobuf::Message for ThpCreateNewSession {
if let Some(v) = self.derive_cardano { if let Some(v) = self.derive_cardano {
os.write_bool(3, v)?; os.write_bool(3, v)?;
} }
if let Some(v) = self.session_id {
os.write_uint32(4, v)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?; os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(()) ::std::result::Result::Ok(())
} }
@ -730,7 +695,6 @@ impl ::protobuf::Message for ThpCreateNewSession {
self.passphrase = ::std::option::Option::None; self.passphrase = ::std::option::Option::None;
self.on_device = ::std::option::Option::None; self.on_device = ::std::option::Option::None;
self.derive_cardano = ::std::option::Option::None; self.derive_cardano = ::std::option::Option::None;
self.session_id = ::std::option::Option::None;
self.special_fields.clear(); self.special_fields.clear();
} }
@ -739,7 +703,6 @@ impl ::protobuf::Message for ThpCreateNewSession {
passphrase: ::std::option::Option::None, passphrase: ::std::option::Option::None,
on_device: ::std::option::Option::None, on_device: ::std::option::Option::None,
derive_cardano: ::std::option::Option::None, derive_cardano: ::std::option::Option::None,
session_id: ::std::option::Option::None,
special_fields: ::protobuf::SpecialFields::new(), special_fields: ::protobuf::SpecialFields::new(),
}; };
&instance &instance
@ -4083,62 +4046,62 @@ static file_descriptor_proto_data: &'static [u8] = b"\
.thp.ThpPairingMethodR\x0epairingMethods\"\xb2\x01\n%ThpHandshakeComplet\ .thp.ThpPairingMethodR\x0epairingMethods\"\xb2\x01\n%ThpHandshakeComplet\
ionReqNoisePayload\x126\n\x17host_pairing_credential\x18\x01\x20\x01(\ ionReqNoisePayload\x126\n\x17host_pairing_credential\x18\x01\x20\x01(\
\x0cR\x15hostPairingCredential\x12Q\n\x0fpairing_methods\x18\x02\x20\x03\ \x0cR\x15hostPairingCredential\x12Q\n\x0fpairing_methods\x18\x02\x20\x03\
(\x0e2(.hw.trezor.messages.thp.ThpPairingMethodR\x0epairingMethods\"\x98\ (\x0e2(.hw.trezor.messages.thp.ThpPairingMethodR\x0epairingMethods\"y\n\
\x01\n\x13ThpCreateNewSession\x12\x1e\n\npassphrase\x18\x01\x20\x01(\tR\ \x13ThpCreateNewSession\x12\x1e\n\npassphrase\x18\x01\x20\x01(\tR\npassp\
\npassphrase\x12\x1b\n\ton_device\x18\x02\x20\x01(\x08R\x08onDevice\x12%\ hrase\x12\x1b\n\ton_device\x18\x02\x20\x01(\x08R\x08onDevice\x12%\n\x0ed\
\n\x0ederive_cardano\x18\x03\x20\x01(\x08R\rderiveCardano\x12\x1d\n\nses\ erive_cardano\x18\x03\x20\x01(\x08R\rderiveCardano\"5\n\rThpNewSession\
sion_id\x18\x04\x20\x01(\rR\tsessionId\"5\n\rThpNewSession\x12$\n\x0enew\ \x12$\n\x0enew_session_id\x18\x01\x20\x01(\rR\x0cnewSessionId\"5\n\x16Th\
_session_id\x18\x01\x20\x01(\rR\x0cnewSessionId\"5\n\x16ThpStartPairingR\ pStartPairingRequest\x12\x1b\n\thost_name\x18\x01\x20\x01(\tR\x08hostNam\
equest\x12\x1b\n\thost_name\x18\x01\x20\x01(\tR\x08hostName\"\x20\n\x1eT\ e\"\x20\n\x1eThpPairingPreparationsFinished\"8\n\x16ThpCodeEntryCommitme\
hpPairingPreparationsFinished\"8\n\x16ThpCodeEntryCommitment\x12\x1e\n\n\ nt\x12\x1e\n\ncommitment\x18\x01\x20\x01(\x0cR\ncommitment\"5\n\x15ThpCo\
commitment\x18\x01\x20\x01(\x0cR\ncommitment\"5\n\x15ThpCodeEntryChallen\ deEntryChallenge\x12\x1c\n\tchallenge\x18\x01\x20\x01(\x0cR\tchallenge\"\
ge\x12\x1c\n\tchallenge\x18\x01\x20\x01(\x0cR\tchallenge\"J\n\x15ThpCode\ J\n\x15ThpCodeEntryCpaceHost\x121\n\x15cpace_host_public_key\x18\x01\x20\
EntryCpaceHost\x121\n\x15cpace_host_public_key\x18\x01\x20\x01(\x0cR\x12\ \x01(\x0cR\x12cpaceHostPublicKey\"P\n\x17ThpCodeEntryCpaceTrezor\x125\n\
cpaceHostPublicKey\"P\n\x17ThpCodeEntryCpaceTrezor\x125\n\x17cpace_trezo\ \x17cpace_trezor_public_key\x18\x01\x20\x01(\x0cR\x14cpaceTrezorPublicKe\
r_public_key\x18\x01\x20\x01(\x0cR\x14cpaceTrezorPublicKey\"#\n\x0fThpCo\ y\"#\n\x0fThpCodeEntryTag\x12\x10\n\x03tag\x18\x02\x20\x01(\x0cR\x03tag\
deEntryTag\x12\x10\n\x03tag\x18\x02\x20\x01(\x0cR\x03tag\",\n\x12ThpCode\ \",\n\x12ThpCodeEntrySecret\x12\x16\n\x06secret\x18\x01\x20\x01(\x0cR\
EntrySecret\x12\x16\n\x06secret\x18\x01\x20\x01(\x0cR\x06secret\"\x20\n\ \x06secret\"\x20\n\x0cThpQrCodeTag\x12\x10\n\x03tag\x18\x01\x20\x01(\x0c\
\x0cThpQrCodeTag\x12\x10\n\x03tag\x18\x01\x20\x01(\x0cR\x03tag\")\n\x0fT\ R\x03tag\")\n\x0fThpQrCodeSecret\x12\x16\n\x06secret\x18\x01\x20\x01(\
hpQrCodeSecret\x12\x16\n\x06secret\x18\x01\x20\x01(\x0cR\x06secret\"+\n\ \x0cR\x06secret\"+\n\x17ThpNfcUnidirectionalTag\x12\x10\n\x03tag\x18\x01\
\x17ThpNfcUnidirectionalTag\x12\x10\n\x03tag\x18\x01\x20\x01(\x0cR\x03ta\ \x20\x01(\x0cR\x03tag\"4\n\x1aThpNfcUnidirectionalSecret\x12\x16\n\x06se\
g\"4\n\x1aThpNfcUnidirectionalSecret\x12\x16\n\x06secret\x18\x01\x20\x01\ cret\x18\x01\x20\x01(\x0cR\x06secret\"D\n\x14ThpCredentialRequest\x12,\n\
(\x0cR\x06secret\"D\n\x14ThpCredentialRequest\x12,\n\x12host_static_pubk\ \x12host_static_pubkey\x18\x01\x20\x01(\x0cR\x10hostStaticPubkey\"i\n\
ey\x18\x01\x20\x01(\x0cR\x10hostStaticPubkey\"i\n\x15ThpCredentialRespon\ \x15ThpCredentialResponse\x120\n\x14trezor_static_pubkey\x18\x01\x20\x01\
se\x120\n\x14trezor_static_pubkey\x18\x01\x20\x01(\x0cR\x12trezorStaticP\ (\x0cR\x12trezorStaticPubkey\x12\x1e\n\ncredential\x18\x02\x20\x01(\x0cR\
ubkey\x12\x1e\n\ncredential\x18\x02\x20\x01(\x0cR\ncredential\"\x0f\n\rT\ \ncredential\"\x0f\n\rThpEndRequest\"\x10\n\x0eThpEndResponse\":\n\x15Th\
hpEndRequest\"\x10\n\x0eThpEndResponse\":\n\x15ThpCredentialMetadata\x12\ pCredentialMetadata\x12\x1b\n\thost_name\x18\x01\x20\x01(\tR\x08hostName\
\x1b\n\thost_name\x18\x01\x20\x01(\tR\x08hostName:\x04\x98\xb2\x19\x01\"\ :\x04\x98\xb2\x19\x01\"\x82\x01\n\x14ThpPairingCredential\x12R\n\rcred_m\
\x82\x01\n\x14ThpPairingCredential\x12R\n\rcred_metadata\x18\x01\x20\x01\ etadata\x18\x01\x20\x01(\x0b2-.hw.trezor.messages.thp.ThpCredentialMetad\
(\x0b2-.hw.trezor.messages.thp.ThpCredentialMetadataR\x0ccredMetadata\ ataR\x0ccredMetadata\x12\x10\n\x03mac\x18\x02\x20\x01(\x0cR\x03mac:\x04\
\x12\x10\n\x03mac\x18\x02\x20\x01(\x0cR\x03mac:\x04\x98\xb2\x19\x01\"\ \x98\xb2\x19\x01\"\xa8\x01\n\x1eThpAuthenticatedCredentialData\x12,\n\
\xa8\x01\n\x1eThpAuthenticatedCredentialData\x12,\n\x12host_static_pubke\ \x12host_static_pubkey\x18\x01\x20\x01(\x0cR\x10hostStaticPubkey\x12R\n\
y\x18\x01\x20\x01(\x0cR\x10hostStaticPubkey\x12R\n\rcred_metadata\x18\ \rcred_metadata\x18\x02\x20\x01(\x0b2-.hw.trezor.messages.thp.ThpCredent\
\x02\x20\x01(\x0b2-.hw.trezor.messages.thp.ThpCredentialMetadataR\x0ccre\ ialMetadataR\x0ccredMetadata:\x04\x98\xb2\x19\x01*\xf6\x06\n\x0eThpMessa\
dMetadata:\x04\x98\xb2\x19\x01*\xf6\x06\n\x0eThpMessageType\x12-\n\"ThpM\ geType\x12-\n\"ThpMessageType_ThpCreateNewSession\x10\xe8\x07\x1a\x04\
essageType_ThpCreateNewSession\x10\xe8\x07\x1a\x04\x80\xa6\x1d\x01\x12'\ \x80\xa6\x1d\x01\x12'\n\x1cThpMessageType_ThpNewSession\x10\xe9\x07\x1a\
\n\x1cThpMessageType_ThpNewSession\x10\xe9\x07\x1a\x04\x80\xa6\x1d\x01\ \x04\x80\xa6\x1d\x01\x120\n%ThpMessageType_ThpStartPairingRequest\x10\
\x120\n%ThpMessageType_ThpStartPairingRequest\x10\xf0\x07\x1a\x04\x80\ \xf0\x07\x1a\x04\x80\xa6\x1d\x01\x128\n-ThpMessageType_ThpPairingPrepara\
\xa6\x1d\x01\x128\n-ThpMessageType_ThpPairingPreparationsFinished\x10\ tionsFinished\x10\xf1\x07\x1a\x04\x80\xa6\x1d\x01\x12.\n#ThpMessageType_\
\xf1\x07\x1a\x04\x80\xa6\x1d\x01\x12.\n#ThpMessageType_ThpCredentialRequ\ ThpCredentialRequest\x10\xf2\x07\x1a\x04\x80\xa6\x1d\x01\x12/\n$ThpMessa\
est\x10\xf2\x07\x1a\x04\x80\xa6\x1d\x01\x12/\n$ThpMessageType_ThpCredent\ geType_ThpCredentialResponse\x10\xf3\x07\x1a\x04\x80\xa6\x1d\x01\x12'\n\
ialResponse\x10\xf3\x07\x1a\x04\x80\xa6\x1d\x01\x12'\n\x1cThpMessageType\ \x1cThpMessageType_ThpEndRequest\x10\xf4\x07\x1a\x04\x80\xa6\x1d\x01\x12\
_ThpEndRequest\x10\xf4\x07\x1a\x04\x80\xa6\x1d\x01\x12(\n\x1dThpMessageT\ (\n\x1dThpMessageType_ThpEndResponse\x10\xf5\x07\x1a\x04\x80\xa6\x1d\x01\
ype_ThpEndResponse\x10\xf5\x07\x1a\x04\x80\xa6\x1d\x01\x120\n%ThpMessage\ \x120\n%ThpMessageType_ThpCodeEntryCommitment\x10\xf8\x07\x1a\x04\x80\
Type_ThpCodeEntryCommitment\x10\xf8\x07\x1a\x04\x80\xa6\x1d\x01\x12/\n$T\ \xa6\x1d\x01\x12/\n$ThpMessageType_ThpCodeEntryChallenge\x10\xf9\x07\x1a\
hpMessageType_ThpCodeEntryChallenge\x10\xf9\x07\x1a\x04\x80\xa6\x1d\x01\ \x04\x80\xa6\x1d\x01\x12/\n$ThpMessageType_ThpCodeEntryCpaceHost\x10\xfa\
\x12/\n$ThpMessageType_ThpCodeEntryCpaceHost\x10\xfa\x07\x1a\x04\x80\xa6\ \x07\x1a\x04\x80\xa6\x1d\x01\x121\n&ThpMessageType_ThpCodeEntryCpaceTrez\
\x1d\x01\x121\n&ThpMessageType_ThpCodeEntryCpaceTrezor\x10\xfb\x07\x1a\ or\x10\xfb\x07\x1a\x04\x80\xa6\x1d\x01\x12)\n\x1eThpMessageType_ThpCodeE\
\x04\x80\xa6\x1d\x01\x12)\n\x1eThpMessageType_ThpCodeEntryTag\x10\xfc\ ntryTag\x10\xfc\x07\x1a\x04\x80\xa6\x1d\x01\x12,\n!ThpMessageType_ThpCod\
\x07\x1a\x04\x80\xa6\x1d\x01\x12,\n!ThpMessageType_ThpCodeEntrySecret\ eEntrySecret\x10\xfd\x07\x1a\x04\x80\xa6\x1d\x01\x12&\n\x1bThpMessageTyp\
\x10\xfd\x07\x1a\x04\x80\xa6\x1d\x01\x12&\n\x1bThpMessageType_ThpQrCodeT\ e_ThpQrCodeTag\x10\x80\x08\x1a\x04\x80\xa6\x1d\x01\x12)\n\x1eThpMessageT\
ag\x10\x80\x08\x1a\x04\x80\xa6\x1d\x01\x12)\n\x1eThpMessageType_ThpQrCod\ ype_ThpQrCodeSecret\x10\x81\x08\x1a\x04\x80\xa6\x1d\x01\x121\n&ThpMessag\
eSecret\x10\x81\x08\x1a\x04\x80\xa6\x1d\x01\x121\n&ThpMessageType_ThpNfc\ eType_ThpNfcUnidirectionalTag\x10\x88\x08\x1a\x04\x80\xa6\x1d\x01\x124\n\
UnidirectionalTag\x10\x88\x08\x1a\x04\x80\xa6\x1d\x01\x124\n)ThpMessageT\ )ThpMessageType_ThpNfcUnidirectionalSecret\x10\x89\x08\x1a\x04\x80\xa6\
ype_ThpNfcUnidirectionalSecret\x10\x89\x08\x1a\x04\x80\xa6\x1d\x01\"\x05\ \x1d\x01\"\x05\x08\0\x10\xe7\x07\"\t\x08\xcc\x08\x10\xff\xff\xff\xff\x07\
\x08\0\x10\xe7\x07\"\t\x08\xcc\x08\x10\xff\xff\xff\xff\x07*S\n\x10ThpPai\ *S\n\x10ThpPairingMethod\x12\x0c\n\x08NoMethod\x10\x01\x12\r\n\tCodeEntr\
ringMethod\x12\x0c\n\x08NoMethod\x10\x01\x12\r\n\tCodeEntry\x10\x02\x12\ y\x10\x02\x12\n\n\x06QrCode\x10\x03\x12\x16\n\x12NFC_Unidirectional\x10\
\n\n\x06QrCode\x10\x03\x12\x16\n\x12NFC_Unidirectional\x10\x04B;\n#com.s\ \x04B;\n#com.satoshilabs.trezor.lib.protobufB\x10TrezorMessageThp\x80\
atoshilabs.trezor.lib.protobufB\x10TrezorMessageThp\x80\xa6\x1d\x01\ \xa6\x1d\x01\
"; ";
/// `FileDescriptorProto` object which was a source for this generated file /// `FileDescriptorProto` object which was a source for this generated file