mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 09:28:13 +00:00
Merge pull request #496 from trezor/tsusanka/pre-slip39
Store mnemonic as bytes
This commit is contained in:
commit
12dd548938
@ -2,7 +2,7 @@ from trezor import wire
|
|||||||
from trezor.crypto import bip32
|
from trezor.crypto import bip32
|
||||||
|
|
||||||
from apps.cardano import SEED_NAMESPACE
|
from apps.cardano import SEED_NAMESPACE
|
||||||
from apps.common import cache, storage
|
from apps.common import cache, mnemonic, storage
|
||||||
from apps.common.request_passphrase import protect_by_passphrase
|
from apps.common.request_passphrase import protect_by_passphrase
|
||||||
|
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ async def get_keychain(ctx: wire.Context) -> Keychain:
|
|||||||
if passphrase is None:
|
if passphrase is None:
|
||||||
passphrase = await protect_by_passphrase(ctx)
|
passphrase = await protect_by_passphrase(ctx)
|
||||||
cache.set_passphrase(passphrase)
|
cache.set_passphrase(passphrase)
|
||||||
root = bip32.from_mnemonic_cardano(storage.get_mnemonic(), passphrase)
|
root = bip32.from_mnemonic_cardano(mnemonic.restore(), passphrase)
|
||||||
|
|
||||||
# derive the namespaced root node
|
# derive the namespaced root node
|
||||||
for i in SEED_NAMESPACE[0]:
|
for i in SEED_NAMESPACE[0]:
|
||||||
|
@ -924,6 +924,46 @@ COINS = [
|
|||||||
decred=False,
|
decred=False,
|
||||||
curve_name='secp256k1',
|
curve_name='secp256k1',
|
||||||
),
|
),
|
||||||
|
CoinInfo(
|
||||||
|
coin_name="Qtum",
|
||||||
|
coin_shortcut="QTUM",
|
||||||
|
address_type=58,
|
||||||
|
address_type_p2sh=50,
|
||||||
|
maxfee_kb=40000000,
|
||||||
|
signed_message_header="Qtum Signed Message:\n",
|
||||||
|
xpub_magic=0x0488b21e,
|
||||||
|
xpub_magic_segwit_p2sh=0x049d7cb2,
|
||||||
|
xpub_magic_segwit_native=0x04b24746,
|
||||||
|
bech32_prefix="qc",
|
||||||
|
cashaddr_prefix=None,
|
||||||
|
slip44=2301,
|
||||||
|
segwit=True,
|
||||||
|
fork_id=None,
|
||||||
|
force_bip143=False,
|
||||||
|
bip115=False,
|
||||||
|
decred=False,
|
||||||
|
curve_name='secp256k1',
|
||||||
|
),
|
||||||
|
CoinInfo(
|
||||||
|
coin_name="Qtum Testnet",
|
||||||
|
coin_shortcut="tQTUM",
|
||||||
|
address_type=120,
|
||||||
|
address_type_p2sh=110,
|
||||||
|
maxfee_kb=40000000,
|
||||||
|
signed_message_header="Qtum Signed Message:\n",
|
||||||
|
xpub_magic=0x043587cf,
|
||||||
|
xpub_magic_segwit_p2sh=0x044a5262,
|
||||||
|
xpub_magic_segwit_native=0x045f1cf6,
|
||||||
|
bech32_prefix="tq",
|
||||||
|
cashaddr_prefix=None,
|
||||||
|
slip44=1,
|
||||||
|
segwit=True,
|
||||||
|
fork_id=None,
|
||||||
|
force_bip143=False,
|
||||||
|
bip115=False,
|
||||||
|
decred=False,
|
||||||
|
curve_name='secp256k1',
|
||||||
|
),
|
||||||
CoinInfo(
|
CoinInfo(
|
||||||
coin_name="Ravencoin",
|
coin_name="Ravencoin",
|
||||||
coin_shortcut="RVN",
|
coin_shortcut="RVN",
|
||||||
|
46
src/apps/common/mnemonic.py
Normal file
46
src/apps/common/mnemonic.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
from trezor import ui
|
||||||
|
from trezor.crypto import bip39
|
||||||
|
|
||||||
|
from apps.common import storage
|
||||||
|
|
||||||
|
TYPE_BIP39 = 0
|
||||||
|
|
||||||
|
|
||||||
|
def get() -> (bytes, int):
|
||||||
|
mnemonic_secret = storage.get_mnemonic_secret()
|
||||||
|
mnemonic_type = storage.get_mnemonic_type()
|
||||||
|
return mnemonic_secret, mnemonic_type
|
||||||
|
|
||||||
|
|
||||||
|
def get_seed(passphrase: str = ""):
|
||||||
|
secret, mnemonic_type = get()
|
||||||
|
_start_progress()
|
||||||
|
if mnemonic_type == TYPE_BIP39:
|
||||||
|
return bip39.seed(secret.decode(), passphrase, _render_progress)
|
||||||
|
|
||||||
|
|
||||||
|
def process(mnemonics: list, mnemonic_type: int):
|
||||||
|
if mnemonic_type == TYPE_BIP39:
|
||||||
|
return mnemonics[0].encode()
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Unknown mnemonic type")
|
||||||
|
|
||||||
|
|
||||||
|
def restore() -> str:
|
||||||
|
secret, mnemonic_type = get()
|
||||||
|
if mnemonic_type == TYPE_BIP39:
|
||||||
|
return secret.decode()
|
||||||
|
|
||||||
|
|
||||||
|
def _start_progress():
|
||||||
|
ui.backlight_slide_sync(ui.BACKLIGHT_DIM)
|
||||||
|
ui.display.clear()
|
||||||
|
ui.header("Please wait")
|
||||||
|
ui.display.refresh()
|
||||||
|
ui.backlight_slide_sync(ui.BACKLIGHT_NORMAL)
|
||||||
|
|
||||||
|
|
||||||
|
def _render_progress(progress: int, total: int):
|
||||||
|
p = int(1000 * progress / total)
|
||||||
|
ui.display.loader(p, 18, ui.WHITE, ui.BG)
|
||||||
|
ui.display.refresh()
|
@ -1,7 +1,7 @@
|
|||||||
from trezor import ui, wire
|
from trezor import ui, wire
|
||||||
from trezor.crypto import bip32, bip39
|
from trezor.crypto import bip32
|
||||||
|
|
||||||
from apps.common import cache, storage
|
from apps.common import cache, mnemonic, storage
|
||||||
from apps.common.request_passphrase import protect_by_passphrase
|
from apps.common.request_passphrase import protect_by_passphrase
|
||||||
|
|
||||||
allow = list
|
allow = list
|
||||||
@ -66,32 +66,17 @@ async def _compute_seed(ctx: wire.Context) -> bytes:
|
|||||||
if passphrase is None:
|
if passphrase is None:
|
||||||
passphrase = await protect_by_passphrase(ctx)
|
passphrase = await protect_by_passphrase(ctx)
|
||||||
cache.set_passphrase(passphrase)
|
cache.set_passphrase(passphrase)
|
||||||
_start_bip39_progress()
|
seed = mnemonic.get_seed(passphrase)
|
||||||
seed = bip39.seed(storage.get_mnemonic(), passphrase, _render_bip39_progress)
|
|
||||||
cache.set_seed(seed)
|
cache.set_seed(seed)
|
||||||
return seed
|
return seed
|
||||||
|
|
||||||
|
|
||||||
def _start_bip39_progress():
|
|
||||||
ui.backlight_slide_sync(ui.BACKLIGHT_DIM)
|
|
||||||
ui.display.clear()
|
|
||||||
ui.header("Please wait")
|
|
||||||
ui.display.refresh()
|
|
||||||
ui.backlight_slide_sync(ui.BACKLIGHT_NORMAL)
|
|
||||||
|
|
||||||
|
|
||||||
def _render_bip39_progress(progress: int, total: int):
|
|
||||||
p = int(1000 * progress / total)
|
|
||||||
ui.display.loader(p, 18, ui.WHITE, ui.BG)
|
|
||||||
ui.display.refresh()
|
|
||||||
|
|
||||||
|
|
||||||
def derive_node_without_passphrase(
|
def derive_node_without_passphrase(
|
||||||
path: list, curve_name: str = "secp256k1"
|
path: list, curve_name: str = "secp256k1"
|
||||||
) -> bip32.HDNode:
|
) -> bip32.HDNode:
|
||||||
if not storage.is_initialized():
|
if not storage.is_initialized():
|
||||||
raise Exception("Device is not initialized")
|
raise Exception("Device is not initialized")
|
||||||
seed = bip39.seed(storage.get_mnemonic(), "")
|
seed = mnemonic.get_seed()
|
||||||
node = bip32.from_seed(seed, curve_name)
|
node = bip32.from_seed(seed, curve_name)
|
||||||
node.derive_path(path)
|
node.derive_path(path)
|
||||||
return node
|
return node
|
||||||
|
@ -18,7 +18,7 @@ _COUNTER_TAIL_LEN = 8
|
|||||||
_APP = const(0x01) # app namespace
|
_APP = const(0x01) # app namespace
|
||||||
_DEVICE_ID = const(0x00) # bytes
|
_DEVICE_ID = const(0x00) # bytes
|
||||||
_VERSION = const(0x01) # int
|
_VERSION = const(0x01) # int
|
||||||
_MNEMONIC = const(0x02) # str
|
_MNEMONIC_SECRET = const(0x02) # bytes
|
||||||
_LANGUAGE = const(0x03) # str
|
_LANGUAGE = const(0x03) # str
|
||||||
_LABEL = const(0x04) # str
|
_LABEL = const(0x04) # str
|
||||||
_USE_PASSPHRASE = const(0x05) # bool (0x01 or empty)
|
_USE_PASSPHRASE = const(0x05) # bool (0x01 or empty)
|
||||||
@ -30,6 +30,7 @@ _PASSPHRASE_SOURCE = const(0x0A) # int
|
|||||||
_UNFINISHED_BACKUP = const(0x0B) # bool (0x01 or empty)
|
_UNFINISHED_BACKUP = const(0x0B) # bool (0x01 or empty)
|
||||||
_AUTOLOCK_DELAY_MS = const(0x0C) # int
|
_AUTOLOCK_DELAY_MS = const(0x0C) # int
|
||||||
_NO_BACKUP = const(0x0D) # bool (0x01 or empty)
|
_NO_BACKUP = const(0x0D) # bool (0x01 or empty)
|
||||||
|
_MNEMONIC_TYPE = const(0x0E) # int
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
|
||||||
@ -44,6 +45,17 @@ def _get_bool(app: int, key: int, public: bool = False) -> bool:
|
|||||||
return config.get(app, key, public) == _TRUE_BYTE
|
return config.get(app, key, public) == _TRUE_BYTE
|
||||||
|
|
||||||
|
|
||||||
|
def _set_uint8(app: int, key: int, val: int):
|
||||||
|
config.set(app, key, val.to_bytes(1, "big"))
|
||||||
|
|
||||||
|
|
||||||
|
def _get_uint8(app: int, key: int) -> int:
|
||||||
|
val = config.get(app, key)
|
||||||
|
if not val:
|
||||||
|
return None
|
||||||
|
return int.from_bytes(val, "big")
|
||||||
|
|
||||||
|
|
||||||
def _new_device_id() -> str:
|
def _new_device_id() -> str:
|
||||||
return hexlify(random.bytes(12)).decode().upper()
|
return hexlify(random.bytes(12)).decode().upper()
|
||||||
|
|
||||||
@ -67,11 +79,15 @@ def get_label() -> str:
|
|||||||
return label.decode()
|
return label.decode()
|
||||||
|
|
||||||
|
|
||||||
def get_mnemonic() -> str:
|
def get_mnemonic_secret() -> bytes:
|
||||||
mnemonic = config.get(_APP, _MNEMONIC)
|
mnemonic = config.get(_APP, _MNEMONIC_SECRET)
|
||||||
if mnemonic is None:
|
if mnemonic is None:
|
||||||
return None
|
return None
|
||||||
return mnemonic.decode()
|
return mnemonic
|
||||||
|
|
||||||
|
|
||||||
|
def get_mnemonic_type() -> int:
|
||||||
|
return _get_uint8(_APP, _MNEMONIC_TYPE)
|
||||||
|
|
||||||
|
|
||||||
def has_passphrase() -> bool:
|
def has_passphrase() -> bool:
|
||||||
@ -82,8 +98,11 @@ def get_homescreen() -> bytes:
|
|||||||
return config.get(_APP, _HOMESCREEN, True) # public
|
return config.get(_APP, _HOMESCREEN, True) # public
|
||||||
|
|
||||||
|
|
||||||
def load_mnemonic(mnemonic: str, needs_backup: bool, no_backup: bool) -> None:
|
def store_mnemonic(
|
||||||
config.set(_APP, _MNEMONIC, mnemonic.encode())
|
secret: bytes, mnemonic_type: int, needs_backup: bool, no_backup: bool
|
||||||
|
) -> None:
|
||||||
|
config.set(_APP, _MNEMONIC_SECRET, secret)
|
||||||
|
_set_uint8(_APP, _MNEMONIC_TYPE, mnemonic_type)
|
||||||
config.set(_APP, _VERSION, _STORAGE_VERSION)
|
config.set(_APP, _VERSION, _STORAGE_VERSION)
|
||||||
_set_bool(_APP, _NO_BACKUP, no_backup)
|
_set_bool(_APP, _NO_BACKUP, no_backup)
|
||||||
if not no_backup:
|
if not no_backup:
|
||||||
|
@ -9,7 +9,7 @@ if __debug__:
|
|||||||
from trezor.messages.DebugLinkState import DebugLinkState
|
from trezor.messages.DebugLinkState import DebugLinkState
|
||||||
from trezor.ui import confirm, swipe
|
from trezor.ui import confirm, swipe
|
||||||
from trezor.wire import register, protobuf_workflow
|
from trezor.wire import register, protobuf_workflow
|
||||||
from apps.common import storage
|
from apps.common import storage, mnemonic
|
||||||
|
|
||||||
reset_internal_entropy = None
|
reset_internal_entropy = None
|
||||||
reset_current_words = None
|
reset_current_words = None
|
||||||
@ -29,7 +29,7 @@ if __debug__:
|
|||||||
|
|
||||||
async def dispatch_DebugLinkGetState(ctx, msg):
|
async def dispatch_DebugLinkGetState(ctx, msg):
|
||||||
m = DebugLinkState()
|
m = DebugLinkState()
|
||||||
m.mnemonic = storage.get_mnemonic()
|
m.mnemonic_secret, m.mnemonic_type = mnemonic.get()
|
||||||
m.passphrase_protection = storage.has_passphrase()
|
m.passphrase_protection = storage.has_passphrase()
|
||||||
m.reset_word_pos = reset_word_index
|
m.reset_word_pos = reset_word_index
|
||||||
m.reset_entropy = reset_internal_entropy
|
m.reset_entropy = reset_internal_entropy
|
||||||
|
@ -142,6 +142,13 @@ NETWORKS = [
|
|||||||
name="Mix",
|
name="Mix",
|
||||||
rskip60=False,
|
rskip60=False,
|
||||||
),
|
),
|
||||||
|
NetworkInfo(
|
||||||
|
chain_id=237,
|
||||||
|
slip44=237,
|
||||||
|
shortcut="DXN",
|
||||||
|
name="DEXON",
|
||||||
|
rskip60=False,
|
||||||
|
),
|
||||||
NetworkInfo(
|
NetworkInfo(
|
||||||
chain_id=820,
|
chain_id=820,
|
||||||
slip44=820,
|
slip44=820,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages.Success import Success
|
from trezor.messages.Success import Success
|
||||||
|
|
||||||
from apps.common import storage
|
from apps.common import mnemonic, storage
|
||||||
from apps.management.reset_device import (
|
from apps.management.reset_device import (
|
||||||
check_mnemonic,
|
check_mnemonic,
|
||||||
show_mnemonic,
|
show_mnemonic,
|
||||||
@ -16,7 +16,7 @@ async def backup_device(ctx, msg):
|
|||||||
if not storage.needs_backup():
|
if not storage.needs_backup():
|
||||||
raise wire.ProcessError("Seed already backed up")
|
raise wire.ProcessError("Seed already backed up")
|
||||||
|
|
||||||
mnemonic = storage.get_mnemonic()
|
words = mnemonic.restore()
|
||||||
|
|
||||||
# warn user about mnemonic safety
|
# warn user about mnemonic safety
|
||||||
await show_warning(ctx)
|
await show_warning(ctx)
|
||||||
@ -26,8 +26,8 @@ async def backup_device(ctx, msg):
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
# show mnemonic and require confirmation of a random word
|
# show mnemonic and require confirmation of a random word
|
||||||
await show_mnemonic(ctx, mnemonic)
|
await show_mnemonic(ctx, words)
|
||||||
if await check_mnemonic(ctx, mnemonic):
|
if await check_mnemonic(ctx, words):
|
||||||
break
|
break
|
||||||
await show_wrong_entry(ctx)
|
await show_wrong_entry(ctx)
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ from trezor.messages.Success import Success
|
|||||||
from trezor.pin import pin_to_int
|
from trezor.pin import pin_to_int
|
||||||
from trezor.ui.text import Text
|
from trezor.ui.text import Text
|
||||||
|
|
||||||
from apps.common import storage
|
from apps.common import mnemonic, storage
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
|
|
||||||
|
|
||||||
@ -24,7 +24,13 @@ async def load_device(ctx, msg):
|
|||||||
text.normal("Continue only if you", "know what you are doing!")
|
text.normal("Continue only if you", "know what you are doing!")
|
||||||
await require_confirm(ctx, text)
|
await require_confirm(ctx, text)
|
||||||
|
|
||||||
storage.load_mnemonic(mnemonic=msg.mnemonic, needs_backup=True, no_backup=False)
|
secret = mnemonic.process([msg.mnemonic], mnemonic.TYPE_BIP39)
|
||||||
|
storage.store_mnemonic(
|
||||||
|
secret=secret,
|
||||||
|
mnemonic_type=mnemonic.TYPE_BIP39,
|
||||||
|
needs_backup=True,
|
||||||
|
no_backup=False,
|
||||||
|
)
|
||||||
storage.load_settings(use_passphrase=msg.passphrase_protection, label=msg.label)
|
storage.load_settings(use_passphrase=msg.passphrase_protection, label=msg.label)
|
||||||
if msg.pin:
|
if msg.pin:
|
||||||
config.change_pin(pin_to_int(""), pin_to_int(msg.pin))
|
config.change_pin(pin_to_int(""), pin_to_int(msg.pin))
|
||||||
|
@ -15,7 +15,7 @@ from trezor.ui.text import Text
|
|||||||
from trezor.ui.word_select import WordSelector
|
from trezor.ui.word_select import WordSelector
|
||||||
from trezor.utils import consteq, format_ordinal
|
from trezor.utils import consteq, format_ordinal
|
||||||
|
|
||||||
from apps.common import storage
|
from apps.common import mnemonic, storage
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
from apps.management.change_pin import request_pin_ack, request_pin_confirm
|
from apps.management.change_pin import request_pin_ack, request_pin_confirm
|
||||||
|
|
||||||
@ -47,11 +47,11 @@ async def recovery_device(ctx, msg):
|
|||||||
wordcount = await request_wordcount(ctx)
|
wordcount = await request_wordcount(ctx)
|
||||||
|
|
||||||
# ask for mnemonic words one by one
|
# ask for mnemonic words one by one
|
||||||
mnemonic = await request_mnemonic(ctx, wordcount)
|
words = await request_mnemonic(ctx, wordcount)
|
||||||
|
|
||||||
# check mnemonic validity
|
# check mnemonic validity
|
||||||
if msg.enforce_wordlist or msg.dry_run:
|
if msg.enforce_wordlist or msg.dry_run:
|
||||||
if not bip39.check(mnemonic):
|
if not bip39.check(words):
|
||||||
raise wire.ProcessError("Mnemonic is not valid")
|
raise wire.ProcessError("Mnemonic is not valid")
|
||||||
|
|
||||||
# ask for pin repeatedly
|
# ask for pin repeatedly
|
||||||
@ -60,10 +60,13 @@ async def recovery_device(ctx, msg):
|
|||||||
else:
|
else:
|
||||||
newpin = ""
|
newpin = ""
|
||||||
|
|
||||||
|
secret = mnemonic.process([words], mnemonic.TYPE_BIP39)
|
||||||
|
|
||||||
# dry run
|
# dry run
|
||||||
if msg.dry_run:
|
if msg.dry_run:
|
||||||
digest_input = sha256(mnemonic).digest()
|
digest_input = sha256(secret).digest()
|
||||||
digest_stored = sha256(storage.get_mnemonic()).digest()
|
stored, _ = mnemonic.get()
|
||||||
|
digest_stored = sha256(stored).digest()
|
||||||
if consteq(digest_stored, digest_input):
|
if consteq(digest_stored, digest_input):
|
||||||
return Success(
|
return Success(
|
||||||
message="The seed is valid and matches the one in the device"
|
message="The seed is valid and matches the one in the device"
|
||||||
@ -78,7 +81,12 @@ async def recovery_device(ctx, msg):
|
|||||||
config.change_pin(pin_to_int(""), pin_to_int(newpin))
|
config.change_pin(pin_to_int(""), pin_to_int(newpin))
|
||||||
storage.set_u2f_counter(msg.u2f_counter)
|
storage.set_u2f_counter(msg.u2f_counter)
|
||||||
storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection)
|
storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection)
|
||||||
storage.load_mnemonic(mnemonic=mnemonic, needs_backup=False, no_backup=False)
|
storage.store_mnemonic(
|
||||||
|
secret=secret,
|
||||||
|
mnemonic_type=mnemonic.TYPE_BIP39,
|
||||||
|
needs_backup=False,
|
||||||
|
no_backup=False,
|
||||||
|
)
|
||||||
|
|
||||||
return Success(message="Device recovered")
|
return Success(message="Device recovered")
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ from trezor.ui.scroll import Scrollpage, animate_swipe, paginate
|
|||||||
from trezor.ui.text import Text
|
from trezor.ui.text import Text
|
||||||
from trezor.utils import chunks, format_ordinal
|
from trezor.utils import chunks, format_ordinal
|
||||||
|
|
||||||
from apps.common import storage
|
from apps.common import mnemonic, storage
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
from apps.management.change_pin import request_pin_confirm
|
from apps.management.change_pin import request_pin_confirm
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ async def reset_device(ctx, msg):
|
|||||||
|
|
||||||
# request external entropy and compute mnemonic
|
# request external entropy and compute mnemonic
|
||||||
ent_ack = await ctx.call(EntropyRequest(), MessageType.EntropyAck)
|
ent_ack = await ctx.call(EntropyRequest(), MessageType.EntropyAck)
|
||||||
mnemonic = generate_mnemonic(msg.strength, internal_ent, ent_ack.entropy)
|
words = generate_mnemonic(msg.strength, internal_ent, ent_ack.entropy)
|
||||||
|
|
||||||
if not msg.skip_backup and not msg.no_backup:
|
if not msg.skip_backup and not msg.no_backup:
|
||||||
# require confirmation of the mnemonic safety
|
# require confirmation of the mnemonic safety
|
||||||
@ -67,8 +67,8 @@ async def reset_device(ctx, msg):
|
|||||||
|
|
||||||
# show mnemonic and require confirmation of a random word
|
# show mnemonic and require confirmation of a random word
|
||||||
while True:
|
while True:
|
||||||
await show_mnemonic(ctx, mnemonic)
|
await show_mnemonic(ctx, words)
|
||||||
if await check_mnemonic(ctx, mnemonic):
|
if await check_mnemonic(ctx, words):
|
||||||
break
|
break
|
||||||
await show_wrong_entry(ctx)
|
await show_wrong_entry(ctx)
|
||||||
|
|
||||||
@ -77,10 +77,14 @@ async def reset_device(ctx, msg):
|
|||||||
if not config.change_pin(pin_to_int(""), pin_to_int(newpin)):
|
if not config.change_pin(pin_to_int(""), pin_to_int(newpin)):
|
||||||
raise wire.ProcessError("Could not change PIN")
|
raise wire.ProcessError("Could not change PIN")
|
||||||
|
|
||||||
|
secret = mnemonic.process([words], mnemonic.TYPE_BIP39)
|
||||||
# write settings and mnemonic into storage
|
# write settings and mnemonic into storage
|
||||||
storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection)
|
storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection)
|
||||||
storage.load_mnemonic(
|
storage.store_mnemonic(
|
||||||
mnemonic=mnemonic, needs_backup=msg.skip_backup, no_backup=msg.no_backup
|
secret=secret,
|
||||||
|
mnemonic_type=mnemonic.TYPE_BIP39,
|
||||||
|
needs_backup=msg.skip_backup,
|
||||||
|
no_backup=msg.no_backup,
|
||||||
)
|
)
|
||||||
|
|
||||||
# show success message. if we skipped backup, it's possible that homescreen
|
# show success message. if we skipped backup, it's possible that homescreen
|
||||||
@ -98,8 +102,7 @@ def generate_mnemonic(strength: int, int_entropy: bytes, ext_entropy: bytes) ->
|
|||||||
ehash.update(int_entropy)
|
ehash.update(int_entropy)
|
||||||
ehash.update(ext_entropy)
|
ehash.update(ext_entropy)
|
||||||
entropy = ehash.digest()
|
entropy = ehash.digest()
|
||||||
mnemonic = bip39.from_data(entropy[: strength // 8])
|
return bip39.from_data(entropy[: strength // 8])
|
||||||
return mnemonic
|
|
||||||
|
|
||||||
|
|
||||||
async def show_warning(ctx):
|
async def show_warning(ctx):
|
||||||
|
19
src/trezor/messages/BinanceAddress.py
Normal file
19
src/trezor/messages/BinanceAddress.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
|
||||||
|
class BinanceAddress(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 701
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
address: str = None,
|
||||||
|
) -> None:
|
||||||
|
self.address = address
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('address', p.UnicodeType, 0),
|
||||||
|
}
|
25
src/trezor/messages/BinanceCancelMsg.py
Normal file
25
src/trezor/messages/BinanceCancelMsg.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
|
||||||
|
class BinanceCancelMsg(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 708
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
refid: str = None,
|
||||||
|
sender: str = None,
|
||||||
|
symbol: str = None,
|
||||||
|
) -> None:
|
||||||
|
self.refid = refid
|
||||||
|
self.sender = sender
|
||||||
|
self.symbol = symbol
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('refid', p.UnicodeType, 0),
|
||||||
|
2: ('sender', p.UnicodeType, 0),
|
||||||
|
3: ('symbol', p.UnicodeType, 0),
|
||||||
|
}
|
28
src/trezor/messages/BinanceGetAddress.py
Normal file
28
src/trezor/messages/BinanceGetAddress.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
if __debug__:
|
||||||
|
try:
|
||||||
|
from typing import List
|
||||||
|
except ImportError:
|
||||||
|
List = None # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class BinanceGetAddress(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 700
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
address_n: List[int] = None,
|
||||||
|
show_display: bool = None,
|
||||||
|
) -> None:
|
||||||
|
self.address_n = address_n if address_n is not None else []
|
||||||
|
self.show_display = show_display
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
|
||||||
|
2: ('show_display', p.BoolType, 0),
|
||||||
|
}
|
28
src/trezor/messages/BinanceGetPublicKey.py
Normal file
28
src/trezor/messages/BinanceGetPublicKey.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
if __debug__:
|
||||||
|
try:
|
||||||
|
from typing import List
|
||||||
|
except ImportError:
|
||||||
|
List = None # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class BinanceGetPublicKey(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 702
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
address_n: List[int] = None,
|
||||||
|
show_display: bool = None,
|
||||||
|
) -> None:
|
||||||
|
self.address_n = address_n if address_n is not None else []
|
||||||
|
self.show_display = show_display
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
|
||||||
|
2: ('show_display', p.BoolType, 0),
|
||||||
|
}
|
40
src/trezor/messages/BinanceOrderMsg.py
Normal file
40
src/trezor/messages/BinanceOrderMsg.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
|
||||||
|
class BinanceOrderMsg(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 707
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: str = None,
|
||||||
|
ordertype: int = None,
|
||||||
|
price: int = None,
|
||||||
|
quantity: int = None,
|
||||||
|
sender: str = None,
|
||||||
|
side: int = None,
|
||||||
|
symbol: str = None,
|
||||||
|
timeinforce: int = None,
|
||||||
|
) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.ordertype = ordertype
|
||||||
|
self.price = price
|
||||||
|
self.quantity = quantity
|
||||||
|
self.sender = sender
|
||||||
|
self.side = side
|
||||||
|
self.symbol = symbol
|
||||||
|
self.timeinforce = timeinforce
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('id', p.UnicodeType, 0),
|
||||||
|
2: ('ordertype', p.UVarintType, 0),
|
||||||
|
3: ('price', p.SVarintType, 0),
|
||||||
|
4: ('quantity', p.SVarintType, 0),
|
||||||
|
5: ('sender', p.UnicodeType, 0),
|
||||||
|
6: ('side', p.UVarintType, 0),
|
||||||
|
7: ('symbol', p.UnicodeType, 0),
|
||||||
|
8: ('timeinforce', p.UVarintType, 0),
|
||||||
|
}
|
19
src/trezor/messages/BinancePublicKey.py
Normal file
19
src/trezor/messages/BinancePublicKey.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
|
||||||
|
class BinancePublicKey(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 703
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
public_key: bytes = None,
|
||||||
|
) -> None:
|
||||||
|
self.public_key = public_key
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('public_key', p.BytesType, 0),
|
||||||
|
}
|
43
src/trezor/messages/BinanceSignTx.py
Normal file
43
src/trezor/messages/BinanceSignTx.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
if __debug__:
|
||||||
|
try:
|
||||||
|
from typing import List
|
||||||
|
except ImportError:
|
||||||
|
List = None # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class BinanceSignTx(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 704
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
address_n: List[int] = None,
|
||||||
|
msg_count: int = None,
|
||||||
|
account_number: int = None,
|
||||||
|
chain_id: str = None,
|
||||||
|
memo: str = None,
|
||||||
|
sequence: int = None,
|
||||||
|
source: int = None,
|
||||||
|
) -> None:
|
||||||
|
self.address_n = address_n if address_n is not None else []
|
||||||
|
self.msg_count = msg_count
|
||||||
|
self.account_number = account_number
|
||||||
|
self.chain_id = chain_id
|
||||||
|
self.memo = memo
|
||||||
|
self.sequence = sequence
|
||||||
|
self.source = source
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
|
||||||
|
2: ('msg_count', p.UVarintType, 0),
|
||||||
|
3: ('account_number', p.SVarintType, 0),
|
||||||
|
4: ('chain_id', p.UnicodeType, 0),
|
||||||
|
5: ('memo', p.UnicodeType, 0),
|
||||||
|
6: ('sequence', p.SVarintType, 0),
|
||||||
|
7: ('source', p.SVarintType, 0),
|
||||||
|
}
|
25
src/trezor/messages/BinanceSignedTx.py
Normal file
25
src/trezor/messages/BinanceSignedTx.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
|
||||||
|
class BinanceSignedTx(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 709
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
signature: bytes = None,
|
||||||
|
public_key: bytes = None,
|
||||||
|
json: str = None,
|
||||||
|
) -> None:
|
||||||
|
self.signature = signature
|
||||||
|
self.public_key = public_key
|
||||||
|
self.json = json
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('signature', p.BytesType, 0),
|
||||||
|
2: ('public_key', p.BytesType, 0),
|
||||||
|
3: ('json', p.UnicodeType, 0),
|
||||||
|
}
|
30
src/trezor/messages/BinanceTransferMsg.py
Normal file
30
src/trezor/messages/BinanceTransferMsg.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
from .InputOutput import InputOutput
|
||||||
|
|
||||||
|
if __debug__:
|
||||||
|
try:
|
||||||
|
from typing import List
|
||||||
|
except ImportError:
|
||||||
|
List = None # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class BinanceTransferMsg(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 706
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
inputs: List[InputOutput] = None,
|
||||||
|
outputs: List[InputOutput] = None,
|
||||||
|
) -> None:
|
||||||
|
self.inputs = inputs if inputs is not None else []
|
||||||
|
self.outputs = outputs if outputs is not None else []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('inputs', InputOutput, p.FLAG_REPEATED),
|
||||||
|
2: ('outputs', InputOutput, p.FLAG_REPEATED),
|
||||||
|
}
|
7
src/trezor/messages/BinanceTxRequest.py
Normal file
7
src/trezor/messages/BinanceTxRequest.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
|
||||||
|
class BinanceTxRequest(p.MessageType):
|
||||||
|
MESSAGE_WIRE_TYPE = 705
|
21
src/trezor/messages/Coin.py
Normal file
21
src/trezor/messages/Coin.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
|
||||||
|
class Coin(p.MessageType):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
amount: int = None,
|
||||||
|
denom: str = None,
|
||||||
|
) -> None:
|
||||||
|
self.amount = amount
|
||||||
|
self.denom = denom
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('amount', p.SVarintType, 0),
|
||||||
|
2: ('denom', p.UnicodeType, 0),
|
||||||
|
}
|
@ -13,7 +13,7 @@ class DebugLinkState(p.MessageType):
|
|||||||
layout: bytes = None,
|
layout: bytes = None,
|
||||||
pin: str = None,
|
pin: str = None,
|
||||||
matrix: str = None,
|
matrix: str = None,
|
||||||
mnemonic: str = None,
|
mnemonic_secret: bytes = None,
|
||||||
node: HDNodeType = None,
|
node: HDNodeType = None,
|
||||||
passphrase_protection: bool = None,
|
passphrase_protection: bool = None,
|
||||||
reset_word: str = None,
|
reset_word: str = None,
|
||||||
@ -21,11 +21,12 @@ class DebugLinkState(p.MessageType):
|
|||||||
recovery_fake_word: str = None,
|
recovery_fake_word: str = None,
|
||||||
recovery_word_pos: int = None,
|
recovery_word_pos: int = None,
|
||||||
reset_word_pos: int = None,
|
reset_word_pos: int = None,
|
||||||
|
mnemonic_type: int = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.layout = layout
|
self.layout = layout
|
||||||
self.pin = pin
|
self.pin = pin
|
||||||
self.matrix = matrix
|
self.matrix = matrix
|
||||||
self.mnemonic = mnemonic
|
self.mnemonic_secret = mnemonic_secret
|
||||||
self.node = node
|
self.node = node
|
||||||
self.passphrase_protection = passphrase_protection
|
self.passphrase_protection = passphrase_protection
|
||||||
self.reset_word = reset_word
|
self.reset_word = reset_word
|
||||||
@ -33,6 +34,7 @@ class DebugLinkState(p.MessageType):
|
|||||||
self.recovery_fake_word = recovery_fake_word
|
self.recovery_fake_word = recovery_fake_word
|
||||||
self.recovery_word_pos = recovery_word_pos
|
self.recovery_word_pos = recovery_word_pos
|
||||||
self.reset_word_pos = reset_word_pos
|
self.reset_word_pos = reset_word_pos
|
||||||
|
self.mnemonic_type = mnemonic_type
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_fields(cls):
|
def get_fields(cls):
|
||||||
@ -40,7 +42,7 @@ class DebugLinkState(p.MessageType):
|
|||||||
1: ('layout', p.BytesType, 0),
|
1: ('layout', p.BytesType, 0),
|
||||||
2: ('pin', p.UnicodeType, 0),
|
2: ('pin', p.UnicodeType, 0),
|
||||||
3: ('matrix', p.UnicodeType, 0),
|
3: ('matrix', p.UnicodeType, 0),
|
||||||
4: ('mnemonic', p.UnicodeType, 0),
|
4: ('mnemonic_secret', p.BytesType, 0),
|
||||||
5: ('node', HDNodeType, 0),
|
5: ('node', HDNodeType, 0),
|
||||||
6: ('passphrase_protection', p.BoolType, 0),
|
6: ('passphrase_protection', p.BoolType, 0),
|
||||||
7: ('reset_word', p.UnicodeType, 0),
|
7: ('reset_word', p.UnicodeType, 0),
|
||||||
@ -48,4 +50,5 @@ class DebugLinkState(p.MessageType):
|
|||||||
9: ('recovery_fake_word', p.UnicodeType, 0),
|
9: ('recovery_fake_word', p.UnicodeType, 0),
|
||||||
10: ('recovery_word_pos', p.UVarintType, 0),
|
10: ('recovery_word_pos', p.UVarintType, 0),
|
||||||
11: ('reset_word_pos', p.UVarintType, 0),
|
11: ('reset_word_pos', p.UVarintType, 0),
|
||||||
|
12: ('mnemonic_type', p.UVarintType, 0),
|
||||||
}
|
}
|
||||||
|
29
src/trezor/messages/InputOutput.py
Normal file
29
src/trezor/messages/InputOutput.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
import protobuf as p
|
||||||
|
|
||||||
|
from .Coin import Coin
|
||||||
|
|
||||||
|
if __debug__:
|
||||||
|
try:
|
||||||
|
from typing import List
|
||||||
|
except ImportError:
|
||||||
|
List = None # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class InputOutput(p.MessageType):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
address: str = None,
|
||||||
|
coins: List[Coin] = None,
|
||||||
|
) -> None:
|
||||||
|
self.address = address
|
||||||
|
self.coins = coins if coins is not None else []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_fields(cls):
|
||||||
|
return {
|
||||||
|
1: ('address', p.UnicodeType, 0),
|
||||||
|
2: ('coins', Coin, p.FLAG_REPEATED),
|
||||||
|
}
|
@ -183,3 +183,13 @@ EosSignTx = 602
|
|||||||
EosTxActionRequest = 603
|
EosTxActionRequest = 603
|
||||||
EosTxActionAck = 604
|
EosTxActionAck = 604
|
||||||
EosSignedTx = 605
|
EosSignedTx = 605
|
||||||
|
BinanceGetAddress = 700
|
||||||
|
BinanceAddress = 701
|
||||||
|
BinanceGetPublicKey = 702
|
||||||
|
BinancePublicKey = 703
|
||||||
|
BinanceSignTx = 704
|
||||||
|
BinanceTxRequest = 705
|
||||||
|
BinanceTransferMsg = 706
|
||||||
|
BinanceOrderMsg = 707
|
||||||
|
BinanceCancelMsg = 708
|
||||||
|
BinanceSignedTx = 709
|
||||||
|
5
src/trezor/messages/OrderSide.py
Normal file
5
src/trezor/messages/OrderSide.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
SIDE_UNKNOWN = 0
|
||||||
|
BUY = 1
|
||||||
|
SELL = 2
|
6
src/trezor/messages/OrderType.py
Normal file
6
src/trezor/messages/OrderType.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
OT_UNKNOWN = 0
|
||||||
|
MARKET = 1
|
||||||
|
LIMIT = 2
|
||||||
|
OT_RESERVED = 3
|
@ -19,6 +19,6 @@ class PublicKey(p.MessageType):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def get_fields(cls):
|
def get_fields(cls):
|
||||||
return {
|
return {
|
||||||
1: ('node', HDNodeType, 0), # required
|
1: ('node', HDNodeType, 0),
|
||||||
2: ('xpub', p.UnicodeType, 0),
|
2: ('xpub', p.UnicodeType, 0),
|
||||||
}
|
}
|
||||||
|
6
src/trezor/messages/TimeInForce.py
Normal file
6
src/trezor/messages/TimeInForce.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
TIF_UNKNOWN = 0
|
||||||
|
GTE = 1
|
||||||
|
TIF_RESERVED = 2
|
||||||
|
IOC = 3
|
2
vendor/trezor-common
vendored
2
vendor/trezor-common
vendored
@ -1 +1 @@
|
|||||||
Subproject commit cb238cb1f134accc4200217d9511115a8f61c6cb
|
Subproject commit c5e54d7535c8772b9a75ff90c506a28526f94267
|
Loading…
Reference in New Issue
Block a user