From 5e0a2ed6d03753f7041f60c0b34932c9ab0eb39b Mon Sep 17 00:00:00 2001 From: matejcik Date: Wed, 5 Apr 2023 17:41:20 +0200 Subject: [PATCH] feat(core/cosi): confirm CoSi path on screen (fixes #2932) --- core/src/apps/misc/cosi_commit.py | 52 ++++++++++++++++++++++++---- tests/device_tests/misc/test_cosi.py | 29 +++++++++------- tests/ui_tests/fixtures.json | 28 ++++++++------- 3 files changed, 78 insertions(+), 31 deletions(-) diff --git a/core/src/apps/misc/cosi_commit.py b/core/src/apps/misc/cosi_commit.py index 856bea1fa..36ea73d5c 100644 --- a/core/src/apps/misc/cosi_commit.py +++ b/core/src/apps/misc/cosi_commit.py @@ -24,11 +24,42 @@ SCHEMA_SLIP18 = PathSchema.parse("m/10018'/address_index'/*'", slip44_id=()) SCHEMA_SLIP26 = PathSchema.parse("m/10026'/[0-2139062143]'/[0-4]'/0'", slip44_id=()) +def _decode_path(address_n: list[int]) -> str | None: + signing_types = { + 0: "bootloader", + 1: "vendor header", + 2: "firmware", + } + + if len(address_n) == 2 and SCHEMA_SLIP18.match(address_n): + signing_type = signing_types.get(unharden(address_n[1])) + if signing_type is None: + return None + return f"T2T1 {signing_type} (old-style)" + + if SCHEMA_SLIP26.match(address_n): + model = unharden(address_n[1]) + signing_type = unharden(address_n[2]) + if model == 0 and signing_type == 3: + return "External definitions" + + model_bytes = model.to_bytes(4, "little") + signing_type_str = signing_types.get(signing_type) + if ( + signing_type_str is not None + and len(model_bytes) == 4 + and all(0x20 <= b <= 0x7E for b in model_bytes) + ): + return f"{model_bytes.decode()} {signing_type_str}" + + return None + + async def cosi_commit(ctx: Context, msg: CosiCommit) -> CosiSignature: import storage.cache as storage_cache from trezor.crypto import cosi from trezor.crypto.curve import ed25519 - from trezor.ui.layouts import confirm_blob + from trezor.ui.layouts import confirm_blob, confirm_text from apps.common import paths from apps.common.keychain import get_keychain @@ -54,13 +85,20 @@ async def cosi_commit(ctx: Context, msg: CosiCommit) -> CosiSignature: if sign_msg.address_n != msg.address_n: raise DataError("Mismatched address_n") - title = "CoSi sign message" - if SCHEMA_SLIP18.match(sign_msg.address_n): - index = unharden(msg.address_n[1]) - title = f"CoSi sign index {index}" - + path_description = _decode_path(sign_msg.address_n) + await confirm_text( + ctx, + "cosi_confirm_key", + "COSI KEYS", + paths.address_n_to_str(sign_msg.address_n), + path_description, + ) await confirm_blob( - ctx, "cosi_sign", title, sign_msg.data, br_code=ButtonRequestType.ProtectCall + ctx, + "cosi_sign", + "COSI DATA", + sign_msg.data, + br_code=ButtonRequestType.ProtectCall, ) # clear nonce from cache diff --git a/tests/device_tests/misc/test_cosi.py b/tests/device_tests/misc/test_cosi.py index ed2a9dde0..e92f24e39 100644 --- a/tests/device_tests/misc/test_cosi.py +++ b/tests/device_tests/misc/test_cosi.py @@ -119,23 +119,28 @@ def test_cosi_different_key(client: Client): @pytest.mark.parametrize( - "model", + "model, image_type", ( - b"T1B1", - b"T2T1", - b"T2B1", - b"T3W1", - b"\xfe\xfe\xfe\xfe", - b"\x00", - b"dog", - b"42", + (b"T1B1", 0), + (b"T2T1", 0), + (b"T2B1", 0), + (b"T3W1", 0), + (b"\xfe\xfe\xfe\xfe", 0), + (b"\x00", 0), + (b"\x00", 3), + (b"dog", 0), + (b"42", 0), + (b"T2B1", 1), + (b"T2B1", 2), + (b"T2B1", 3), ), ) @pytest.mark.skip_t1 -def test_slip26_paths(client: Client, model: bytes): +def test_slip26_paths(client: Client, model: bytes, image_type: int): slip26_model = int.from_bytes(model, "little") - path = Address([H_(10026), H_(slip26_model), H_(0), H_(0)]) - cosi.commit(client, path) + path = Address([H_(10026), H_(slip26_model), H_(image_type), H_(0)]) + commit = cosi.commit(client, path) + cosi.sign(client, path, DIGEST, commit.commitment, commit.pubkey) @pytest.mark.parametrize( diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index 3f2c5c8c0..2a8310bd5 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -1553,25 +1553,29 @@ "TT_ethereum-test_signtx.py::test_signtx_eip1559_access_list": "b264ed441f5523763477a17cf573353e36b25ead03a0092eaa028d85a0aebf86", "TT_ethereum-test_signtx.py::test_signtx_eip1559_access_list_larger": "b264ed441f5523763477a17cf573353e36b25ead03a0092eaa028d85a0aebf86", "TT_misc-test_cosi.py::test_cosi_different_key": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", -"TT_misc-test_cosi.py::test_cosi_nonce": "0b928abfc966be941fc7f28c847a8e818e7fecba25ac333f8cfe09e3a939d5ff", +"TT_misc-test_cosi.py::test_cosi_nonce": "764a18afe29e5688c1eaaa8eb81b01ce8596754387e26029e40d07259c505a60", "TT_misc-test_cosi.py::test_cosi_pubkey": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", -"TT_misc-test_cosi.py::test_cosi_sign1": "0b928abfc966be941fc7f28c847a8e818e7fecba25ac333f8cfe09e3a939d5ff", -"TT_misc-test_cosi.py::test_cosi_sign2": "6e3b30d39527f2e09f455bc61293e836b6114d5102adca06f6c4b148bdf3ae65", -"TT_misc-test_cosi.py::test_cosi_sign3": "3ebcb064e73dee675470fdd8373c5a4a6dffdcf31c9a25dbf541720a499e7dc2", +"TT_misc-test_cosi.py::test_cosi_sign1": "764a18afe29e5688c1eaaa8eb81b01ce8596754387e26029e40d07259c505a60", +"TT_misc-test_cosi.py::test_cosi_sign2": "b120eb39efdbe2247f58cd81b3facc5491440f96218970091c625aa70703b1aa", +"TT_misc-test_cosi.py::test_cosi_sign3": "fc1a0ffb76942bd17d3fb8e787916574cd667d34c83c5ceefe7a4c547ec0f498", "TT_misc-test_cosi.py::test_invalid_path[m-10018-0]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", "TT_misc-test_cosi.py::test_invalid_path[m-1]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", "TT_misc-test_cosi.py::test_invalid_path[m-44h-0h-0h-0-0]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", "TT_misc-test_cosi.py::test_invalid_path[m-44h-60h-0h-0-0]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", "TT_misc-test_cosi.py::test_invalid_path[m-44h-60h-1h]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", "TT_misc-test_cosi.py::test_invalid_path[m-84h-60h-1h-0]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", -"TT_misc-test_cosi.py::test_slip26_paths[42]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", -"TT_misc-test_cosi.py::test_slip26_paths[T1B1]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", -"TT_misc-test_cosi.py::test_slip26_paths[T2B1]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", -"TT_misc-test_cosi.py::test_slip26_paths[T2T1]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", -"TT_misc-test_cosi.py::test_slip26_paths[T3W1]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", -"TT_misc-test_cosi.py::test_slip26_paths[\\x00]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", -"TT_misc-test_cosi.py::test_slip26_paths[\\xfe\\xfe\\xfe\\xfe]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", -"TT_misc-test_cosi.py::test_slip26_paths[dog]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", +"TT_misc-test_cosi.py::test_slip26_paths[42-0]": "a9a68b24cf57ba9db5c6ecf12be57a3365c99fe134aa8cb0a6ae9c329b6fcf89", +"TT_misc-test_cosi.py::test_slip26_paths[T1B1-0]": "645cf986f8a74e78b61244776d61df7af2232f4a301887869ed45649e2a9b157", +"TT_misc-test_cosi.py::test_slip26_paths[T2B1-0]": "bb5b822fd99fce331cc99c2fa01c41fc217d6ff50f71c2260bbc19866992c4c2", +"TT_misc-test_cosi.py::test_slip26_paths[T2B1-1]": "409138f1387491751d1b53a8bafbd808aeb45ce3e18e2fb798475ac973065bfb", +"TT_misc-test_cosi.py::test_slip26_paths[T2B1-2]": "c936e66013e45bd9bdb7dfdf07a212245d094d5490149007ad06c42a4dd28ed8", +"TT_misc-test_cosi.py::test_slip26_paths[T2B1-3]": "3635436ac3195aeaf49b51df39209ad957097f495471ad872b2aa54018a988c6", +"TT_misc-test_cosi.py::test_slip26_paths[T2T1-0]": "36d998876e82bc6ab70d08d0eb57ec0a8cd26a1e004bbaf46e9d0cfb41157ace", +"TT_misc-test_cosi.py::test_slip26_paths[T3W1-0]": "b29d0cc86f118be1882485dcf7a3e1b41ce1b0b30759296d9cc1c454217c67b8", +"TT_misc-test_cosi.py::test_slip26_paths[\\x00-0]": "65423c052a47dbe8ea903a0e4c6ddef46e5809368e4e0a4437bbf6835510a5a5", +"TT_misc-test_cosi.py::test_slip26_paths[\\x00-3]": "a99f1023e706e89bae3dc7e984e12d22eb6fccbd0b78fdd51f18878144a59a44", +"TT_misc-test_cosi.py::test_slip26_paths[\\xfe\\xfe\\xfe\\xfe-0]": "9e0bd23f3551aa8fda80ce9d4381de67a9abdb03408a731bd7db454a8df407bd", +"TT_misc-test_cosi.py::test_slip26_paths[dog-0]": "56807a9fc3dcb619584ed7e4cbd39adbd6b0e99e9284957f1833ed229bdd04e1", "TT_misc-test_msg_cipherkeyvalue.py::test_decrypt": "a4b1670360e68489d316755ce366aa152f59604aacce498ca7d79e0588d031a6", "TT_misc-test_msg_cipherkeyvalue.py::test_decrypt_badlen": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", "TT_misc-test_msg_cipherkeyvalue.py::test_encrypt": "2e1bfb6721f7859eeb5e40b55c52e82dbc35207bf522de3c88516783ba3b14dc",