You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/src/apps/common/paths.py

85 lines
2.2 KiB

from micropython import const
from trezor import ui
from trezor.messages import ButtonRequestType
from trezor.ui.text import Text
from apps.common import HARDENED
from apps.common.confirm import require_confirm
if False:
from typing import Any, Callable, List
from trezor import wire
from apps.common import seed
async def validate_path(
ctx: wire.Context,
validate_func: Callable[..., bool],
keychain: seed.Keychain,
path: List[int],
curve: str,
**kwargs: Any,
) -> None:
keychain.validate_path(path, curve)
if not validate_func(path, **kwargs):
await show_path_warning(ctx, path)
async def show_path_warning(ctx: wire.Context, path: List[int]) -> None:
text = Text("Confirm path", ui.ICON_WRONG, ui.RED)
text.normal("Path")
text.mono(*break_address_n_to_lines(path))
text.normal("is unknown.")
text.normal("Are you sure?")
await require_confirm(ctx, text, ButtonRequestType.UnknownDerivationPath)
def validate_path_for_get_public_key(path: list, slip44_id: int) -> bool:
"""
Checks if path has at least three hardened items and slip44 id matches.
The path is allowed to have more than three items, but all the following
items have to be non-hardened.
"""
length = len(path)
if length < 3 or length > 5:
return False
if path[0] != 44 | HARDENED:
return False
if path[1] != slip44_id | HARDENED:
return False
if path[2] < HARDENED or path[2] > 20 | HARDENED:
return False
if length > 3 and is_hardened(path[3]):
return False
if length > 4 and is_hardened(path[4]):
return False
return True
def is_hardened(i: int) -> bool:
if i & HARDENED:
return True
else:
return False
def break_address_n_to_lines(address_n: list) -> list:
def path_item(i: int) -> str:
if i & HARDENED:
return str(i ^ HARDENED) + "'"
else:
return str(i)
lines = []
path_str = "m/" + "/".join([path_item(i) for i in address_n])
per_line = const(17)
while len(path_str) > per_line:
i = path_str[:per_line].rfind("/")
lines.append(path_str[:i])
path_str = path_str[i:]
lines.append(path_str)
return lines