src/apps/common: rework PassphraseState behaviour
This commit is contained in:
parent
01bb1e34fa
commit
2e3dc8b29d
|
@ -4,28 +4,26 @@ from apps.common import storage
|
||||||
memory = {}
|
memory = {}
|
||||||
_seed = None
|
_seed = None
|
||||||
_passphrase = None
|
_passphrase = None
|
||||||
_state_salt = None
|
|
||||||
|
|
||||||
|
|
||||||
def get_state(salt: bytes=None, passphrase: str=None):
|
def get_state(state: bytes=None, passphrase: str=None):
|
||||||
global _passphrase, _state_salt
|
|
||||||
if salt is None:
|
if state is None:
|
||||||
# generate a random salt if not provided and not already cached
|
salt = random.bytes(32) # generate a random salt if no state provided
|
||||||
if _state_salt is None:
|
|
||||||
_state_salt = random.bytes(32)
|
|
||||||
else:
|
else:
|
||||||
# otherwise copy provided salt to cached salt
|
salt = state[:32] # use salt from provided state
|
||||||
_state_salt = salt
|
|
||||||
|
if passphrase is None:
|
||||||
|
global _passphrase
|
||||||
|
if _passphrase is None:
|
||||||
|
return None
|
||||||
|
passphrase = _passphrase # use cached passphrase
|
||||||
|
|
||||||
# state = HMAC(passphrase, salt || device_id)
|
# state = HMAC(passphrase, salt || device_id)
|
||||||
if passphrase is None:
|
msg = salt + storage.get_device_id().encode()
|
||||||
key = _passphrase if _passphrase is not None else ''
|
state = hmac.new(passphrase.encode(), msg, hashlib.sha256).digest()
|
||||||
else:
|
|
||||||
key = passphrase
|
|
||||||
msg = _state_salt + storage.get_device_id().encode()
|
|
||||||
state = hmac.new(key.encode(), msg, hashlib.sha256).digest()
|
|
||||||
|
|
||||||
return _state_salt + state
|
return salt + state
|
||||||
|
|
||||||
|
|
||||||
def get_seed():
|
def get_seed():
|
||||||
|
@ -45,6 +43,4 @@ def has_passphrase():
|
||||||
|
|
||||||
def clear():
|
def clear():
|
||||||
global _seed, _passphrase
|
global _seed, _passphrase
|
||||||
global _state_salt
|
|
||||||
_seed, _passphrase = None, None
|
_seed, _passphrase = None, None
|
||||||
_state_salt = None
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ from trezor.messages import ButtonRequestType, wire_types
|
||||||
from trezor.messages.ButtonRequest import ButtonRequest
|
from trezor.messages.ButtonRequest import ButtonRequest
|
||||||
from trezor.messages.FailureType import ActionCancelled, ProcessError
|
from trezor.messages.FailureType import ActionCancelled, ProcessError
|
||||||
from trezor.messages.PassphraseRequest import PassphraseRequest
|
from trezor.messages.PassphraseRequest import PassphraseRequest
|
||||||
|
from trezor.messages.PassphraseStateRequest import PassphraseStateRequest
|
||||||
from trezor.ui.entry_select import DEVICE, EntrySelector
|
from trezor.ui.entry_select import DEVICE, EntrySelector
|
||||||
from trezor.ui.passphrase import CANCELLED, PassphraseKeyboard
|
from trezor.ui.passphrase import CANCELLED, PassphraseKeyboard
|
||||||
from trezor.ui.text import Text
|
from trezor.ui.text import Text
|
||||||
|
@ -53,15 +54,15 @@ async def request_passphrase_ack(ctx, on_device):
|
||||||
raise wire.FailureError(ProcessError, 'Passphrase not provided')
|
raise wire.FailureError(ProcessError, 'Passphrase not provided')
|
||||||
passphrase = ack.passphrase
|
passphrase = ack.passphrase
|
||||||
|
|
||||||
return ack.state, passphrase
|
req = PassphraseStateRequest(state=get_state(state=ack.state, passphrase=passphrase))
|
||||||
|
ack = await ctx.call(req, wire_types.PassphraseStateAck, wire_types.Cancel)
|
||||||
|
|
||||||
|
return passphrase
|
||||||
|
|
||||||
|
|
||||||
async def request_passphrase(ctx):
|
async def request_passphrase(ctx):
|
||||||
on_device = await request_passphrase_entry(ctx) == DEVICE
|
on_device = await request_passphrase_entry(ctx) == DEVICE
|
||||||
state, passphrase = await request_passphrase_ack(ctx, on_device)
|
passphrase = await request_passphrase_ack(ctx, on_device)
|
||||||
if state is not None:
|
|
||||||
if state != get_state(salt=state[:32], passphrase=passphrase):
|
|
||||||
raise wire.FailureError(ProcessError, 'Passphrase mismatch')
|
|
||||||
return passphrase
|
return passphrase
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ from apps.common import storage, coins, cache
|
||||||
async def respond_Features(ctx, msg):
|
async def respond_Features(ctx, msg):
|
||||||
|
|
||||||
if msg.__qualname__ == 'Initialize':
|
if msg.__qualname__ == 'Initialize':
|
||||||
if msg.state is None or msg.state != cache.get_state(salt=msg.state[:32]):
|
if msg.state is None or msg.state != cache.get_state(state=msg.state):
|
||||||
cache.clear()
|
cache.clear()
|
||||||
|
|
||||||
f = Features()
|
f = Features()
|
||||||
|
@ -32,7 +32,6 @@ async def respond_Features(ctx, msg):
|
||||||
f.needs_backup = storage.needs_backup()
|
f.needs_backup = storage.needs_backup()
|
||||||
f.flags = storage.get_flags()
|
f.flags = storage.get_flags()
|
||||||
f.model = 'T'
|
f.model = 'T'
|
||||||
f.state = cache.get_state()
|
|
||||||
|
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ class Features(p.MessageType):
|
||||||
24: ('fw_patch', p.UVarintType, 0),
|
24: ('fw_patch', p.UVarintType, 0),
|
||||||
25: ('fw_vendor', p.UnicodeType, 0),
|
25: ('fw_vendor', p.UnicodeType, 0),
|
||||||
26: ('fw_vendor_keys', p.BytesType, 0),
|
26: ('fw_vendor_keys', p.BytesType, 0),
|
||||||
27: ('state', p.BytesType, 0),
|
|
||||||
}
|
}
|
||||||
MESSAGE_WIRE_TYPE = 17
|
MESSAGE_WIRE_TYPE = 17
|
||||||
|
|
||||||
|
@ -63,7 +62,6 @@ class Features(p.MessageType):
|
||||||
fw_patch: int = None,
|
fw_patch: int = None,
|
||||||
fw_vendor: str = None,
|
fw_vendor: str = None,
|
||||||
fw_vendor_keys: bytes = None,
|
fw_vendor_keys: bytes = None,
|
||||||
state: bytes = None,
|
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
self.vendor = vendor
|
self.vendor = vendor
|
||||||
|
@ -92,5 +90,4 @@ class Features(p.MessageType):
|
||||||
self.fw_patch = fw_patch
|
self.fw_patch = fw_patch
|
||||||
self.fw_vendor = fw_vendor
|
self.fw_vendor = fw_vendor
|
||||||
self.fw_vendor_keys = fw_vendor_keys
|
self.fw_vendor_keys = fw_vendor_keys
|
||||||
self.state = state
|
|
||||||
p.MessageType.__init__(self, **kwargs)
|
p.MessageType.__init__(self, **kwargs)
|
||||||
|
|
|
@ -41,6 +41,8 @@ VerifyMessage = const(39)
|
||||||
MessageSignature = const(40)
|
MessageSignature = const(40)
|
||||||
PassphraseRequest = const(41)
|
PassphraseRequest = const(41)
|
||||||
PassphraseAck = const(42)
|
PassphraseAck = const(42)
|
||||||
|
PassphraseStateRequest = const(77)
|
||||||
|
PassphraseStateAck = const(78)
|
||||||
EstimateTxSize = const(43)
|
EstimateTxSize = const(43)
|
||||||
TxSize = const(44)
|
TxSize = const(44)
|
||||||
RecoveryDevice = const(45)
|
RecoveryDevice = const(45)
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Automatically generated by pb2py
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
|
||||||
|
class PassphraseStateAck(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 78
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
p.MessageType.__init__(self, **kwargs)
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Automatically generated by pb2py
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
|
||||||
|
class PassphraseStateRequest(p.MessageType):
|
||||||
|
FIELDS = {
|
||||||
|
1: ('state', p.BytesType, 0),
|
||||||
|
}
|
||||||
|
MESSAGE_WIRE_TYPE = 77
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
state: bytes = None,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
self.state = state
|
||||||
|
p.MessageType.__init__(self, **kwargs)
|
|
@ -63,6 +63,8 @@ NEMSignTx = const(69)
|
||||||
NEMSignedTx = const(70)
|
NEMSignedTx = const(70)
|
||||||
PassphraseAck = const(42)
|
PassphraseAck = const(42)
|
||||||
PassphraseRequest = const(41)
|
PassphraseRequest = const(41)
|
||||||
|
PassphraseStateAck = const(78)
|
||||||
|
PassphraseStateRequest = const(77)
|
||||||
PinMatrixAck = const(19)
|
PinMatrixAck = const(19)
|
||||||
PinMatrixRequest = const(18)
|
PinMatrixRequest = const(18)
|
||||||
Ping = const(1)
|
Ping = const(1)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit d85f7ac6bbcccbc83012d85fdf25635e57c5f15b
|
Subproject commit 0924bd6826bb63f66010e2e511356d54ea733df3
|
Loading…
Reference in New Issue