2018-02-27 15:35:21 +00:00
|
|
|
from trezor.crypto import hashlib, hmac, random
|
2018-07-03 14:20:26 +00:00
|
|
|
|
2018-02-27 15:35:21 +00:00
|
|
|
from apps.common import storage
|
2018-02-24 17:58:02 +00:00
|
|
|
|
2018-05-28 13:20:31 +00:00
|
|
|
_cached_seed = None
|
|
|
|
_cached_passphrase = None
|
2018-02-24 17:58:02 +00:00
|
|
|
|
|
|
|
|
2018-05-28 13:20:31 +00:00
|
|
|
def get_state(prev_state: bytes = None, passphrase: str = None) -> bytes:
|
|
|
|
if prev_state is None:
|
2018-02-28 23:07:45 +00:00
|
|
|
salt = random.bytes(32) # generate a random salt if no state provided
|
2018-02-24 17:58:02 +00:00
|
|
|
else:
|
2018-05-28 13:20:31 +00:00
|
|
|
salt = prev_state[:32] # use salt from provided state
|
|
|
|
if len(salt) != 32:
|
|
|
|
return None # invalid state
|
2018-02-24 17:58:02 +00:00
|
|
|
if passphrase is None:
|
2018-05-28 13:20:31 +00:00
|
|
|
if _cached_passphrase is None:
|
|
|
|
return None # we don't have any passphrase to compute the state
|
|
|
|
else:
|
|
|
|
passphrase = _cached_passphrase # use cached passphrase
|
|
|
|
return _compute_state(salt, passphrase)
|
2018-02-28 23:07:45 +00:00
|
|
|
|
2017-05-08 20:31:21 +00:00
|
|
|
|
2018-05-28 13:20:31 +00:00
|
|
|
def _compute_state(salt: bytes, passphrase: str) -> bytes:
|
|
|
|
# state = HMAC(passphrase, salt || device_id)
|
|
|
|
message = salt + storage.get_device_id().encode()
|
|
|
|
state = hmac.new(passphrase.encode(), message, hashlib.sha256).digest()
|
2018-02-28 23:07:45 +00:00
|
|
|
return salt + state
|
2018-02-09 17:59:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
def get_seed():
|
2018-05-28 13:20:31 +00:00
|
|
|
return _cached_seed
|
2018-02-09 17:59:26 +00:00
|
|
|
|
|
|
|
|
2018-05-28 13:20:31 +00:00
|
|
|
def get_passphrase():
|
|
|
|
return _cached_passphrase
|
2018-02-09 17:07:47 +00:00
|
|
|
|
|
|
|
|
2018-02-27 19:48:01 +00:00
|
|
|
def has_passphrase():
|
2018-05-28 13:20:31 +00:00
|
|
|
return _cached_passphrase is not None
|
|
|
|
|
2018-02-27 19:48:01 +00:00
|
|
|
|
2018-05-28 13:20:31 +00:00
|
|
|
def set_seed(seed):
|
|
|
|
global _cached_seed
|
|
|
|
_cached_seed = seed
|
2018-02-27 19:48:01 +00:00
|
|
|
|
2018-05-28 13:20:31 +00:00
|
|
|
|
|
|
|
def set_passphrase(passphrase):
|
|
|
|
global _cached_passphrase
|
|
|
|
_cached_passphrase = passphrase
|
|
|
|
|
|
|
|
|
|
|
|
def clear(skip_passphrase: bool = False):
|
|
|
|
set_seed(None)
|
|
|
|
if skip_passphrase:
|
2018-07-03 14:20:58 +00:00
|
|
|
set_passphrase("")
|
2018-05-28 13:20:31 +00:00
|
|
|
else:
|
|
|
|
set_passphrase(None)
|