From 683d7420ff7de5aa9da8ce34c7c2ac129d057227 Mon Sep 17 00:00:00 2001 From: gabrielkerekes Date: Tue, 4 Aug 2020 12:24:53 +0200 Subject: [PATCH] Fix Cardano Shelley public key validation In Shelley Cardano started using the purpose 1852'. Unfortunately, we completely missed that the public key path validation fuction checks for purpose 44' explicitly, which means that the user is shown a warning when deriving public key with the purpose 1852'. Which is always when "logging in" to a wallet. This commit should fix that. I've also updated type hinting in get_public_key. --- core/src/apps/cardano/get_public_key.py | 45 ++++++++++++++++++++----- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/core/src/apps/cardano/get_public_key.py b/core/src/apps/cardano/get_public_key.py index 7a0f3001bb..1ab5d4e684 100644 --- a/core/src/apps/cardano/get_public_key.py +++ b/core/src/apps/cardano/get_public_key.py @@ -4,21 +4,23 @@ from trezor import log, wire from trezor.messages.CardanoPublicKey import CardanoPublicKey from trezor.messages.HDNodeType import HDNodeType -from apps.common import layout, paths +from apps.common import HARDENED, layout, paths from apps.common.seed import remove_ed25519_prefix from . import CURVE, seed +from .helpers import purposes + +if False: + from typing import List + from trezor.messages import CardanoGetPublicKey @seed.with_keychain -async def get_public_key(ctx, msg, keychain: seed.Keychain): +async def get_public_key( + ctx: wire.Context, msg: CardanoGetPublicKey, keychain: seed.Keychain +): await paths.validate_path( - ctx, - paths.validate_path_for_get_public_key, - keychain, - msg.address_n, - CURVE, - slip44_id=1815, + ctx, _validate_path_for_get_public_key, keychain, msg.address_n, CURVE, ) try: @@ -33,7 +35,9 @@ async def get_public_key(ctx, msg, keychain: seed.Keychain): return key -def _get_public_key(keychain, derivation_path: list): +def _get_public_key( + keychain: seed.Keychain, derivation_path: List[int] +) -> CardanoPublicKey: node = keychain.derive(derivation_path) public_key = hexlify(remove_ed25519_prefix(node.public_key())).decode() @@ -49,3 +53,26 @@ def _get_public_key(keychain, derivation_path: list): ) return CardanoPublicKey(node=node_type, xpub=xpub_key) + + +def _validate_path_for_get_public_key(path: List[int]) -> bool: + """ + Modified version of paths.validate_path_for_get_public_key. + Checks if path has at least three hardened items, Byron or Shelley purpose + and slip44 id 1815. 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] not in (purposes.BYRON, purposes.SHELLEY): + return False + if path[1] != 1815 | HARDENED: + return False + if path[2] < HARDENED or path[2] > 20 | HARDENED: + return False + if length > 3 and paths.is_hardened(path[3]): + return False + if length > 4 and paths.is_hardened(path[4]): + return False + return True