From 802958bc0572f6d3f61fb4fdea2860324a994c5f Mon Sep 17 00:00:00 2001 From: matejcik Date: Wed, 28 Feb 2024 11:01:32 +0100 Subject: [PATCH] tests: test that trailing data in translations header will be accepted --- tests/device_tests/test_language.py | 27 ++++++++++++++++++++++++++- tests/translations.py | 16 +++++++++++++--- tests/ui_tests/fixtures.json | 10 ++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/tests/device_tests/test_language.py b/tests/device_tests/test_language.py index 5f6f159e9c..1197b9752d 100644 --- a/tests/device_tests/test_language.py +++ b/tests/device_tests/test_language.py @@ -25,7 +25,14 @@ from trezorlib import debuglink, device, exceptions, messages, models from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import message_filters -from ..translations import LANGUAGES, build_and_sign_blob, get_lang_json, set_language +from ..translations import ( + LANGUAGES, + build_and_sign_blob, + get_lang_json, + prepare_blob, + set_language, + sign_blob, +) pytestmark = pytest.mark.skip_t1b1 @@ -339,3 +346,21 @@ def test_switch_language(client: Client): # switch back to Czech with display, implicitly _maybe_confirm_set_language(client, "cs", None, True) + + +def test_header_trailing_data(client: Client): + """Adding trailing data to _header_ section specifically must be accepted by + firmware, as long as the blob is otherwise valid and signed. + + (this ensures forwards compatibility if we extend the header) + """ + assert client.features.language == "en-US" + lang = "cs" + blob = prepare_blob(lang, client.model) + blob.header_bytes += b"trailing dataa" + assert len(blob.header_bytes) % 2 == 0, "Trailing data must keep the 2-alignment" + language_data = sign_blob(blob) + + device.change_language(client, language_data) + assert client.features.language == "cs-CZ" + _check_ping_screen_texts(client, get_ping_title(lang), get_ping_button(lang)) diff --git a/tests/translations.py b/tests/translations.py index 492234dbfc..6f45d134fb 100644 --- a/tests/translations.py +++ b/tests/translations.py @@ -19,10 +19,10 @@ ORDER_FILE = TRANSLATIONS / "order.json" LANGUAGES = [file.stem for file in TRANSLATIONS.glob("??.json")] -def build_and_sign_blob( +def prepare_blob( lang_or_def: translations.JsonDef | Path | str, model: models.TrezorModel, -) -> bytes: +) -> translations.TranslationsBlob: order = translations.order_from_json(json.loads(ORDER_FILE.read_text())) if isinstance(lang_or_def, str): lang_or_def = get_lang_json(lang_or_def) @@ -31,8 +31,10 @@ def build_and_sign_blob( # generate raw blob version = translations.version_from_json(lang_or_def["header"]["version"]) - blob = translations.blob_from_defs(lang_or_def, order, model, version, FONTS_DIR) + return translations.blob_from_defs(lang_or_def, order, model, version, FONTS_DIR) + +def sign_blob(blob: translations.TranslationsBlob) -> bytes: # build 0-item Merkle proof digest = sha256(b"\x00" + blob.header_bytes).digest() signature = cosi.sign_with_privkeys(digest, common.PRIVATE_KEYS_DEV) @@ -44,6 +46,14 @@ def build_and_sign_blob( return blob.build() +def build_and_sign_blob( + lang_or_def: translations.JsonDef | Path | str, + model: models.TrezorModel, +) -> bytes: + blob = prepare_blob(lang_or_def, model) + return sign_blob(blob) + + def set_language(client: Client, lang: str): if lang.startswith("en"): language_data = b"" diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index 90932f971a..9814244b87 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -3656,6 +3656,7 @@ "TR_cs_test_language.py::test_full_language_change[en]": "f88a93b5fc559b5b3ad60f8db835f0c887fa6db9ef7532066d6dad96c5efac83", "TR_cs_test_language.py::test_full_language_change[es]": "6c6f5261a3b2feeb2cb1393cddbccfff23bef9ef9b9803eed80a503a3cdc4a20", "TR_cs_test_language.py::test_full_language_change[fr]": "18ef4870bf5ee29d49ece9e92910bf3772e5bebde6c642929126d22a84086557", +"TR_cs_test_language.py::test_header_trailing_data": "ca1ce911f38488122f34815eae9545bdff0b625c53b6936e442a30a4b15655b5", "TR_cs_test_language.py::test_language_is_removed_after_wipe": "3fed5c087d565830eae7c0647a4c1ef9350595f550062ae575a97f50cdd7d826", "TR_cs_test_language.py::test_reject_update": "94873b672e55ac3a766fe78cce140e27fe5fbbe4a837bc0e64bb46592ec5d4e3", "TR_cs_test_language.py::test_silent_first_install[False-False]": "cfca3550117beb0f44e6fecb844dfbbf2a182dd440a117398ff04603b6d365f2", @@ -5023,6 +5024,7 @@ "TR_de_test_language.py::test_full_language_change[en]": "a35bc4501de8bae861d757421e17440a21f7d4f3ce1a56bfadabe9e5b467e4a2", "TR_de_test_language.py::test_full_language_change[es]": "2fd72d78dd1d1176ac6aecdfd3ea790aa2aafac0d705b406d44c0e9c9545002c", "TR_de_test_language.py::test_full_language_change[fr]": "fda57886e4c371f3219a29dd54b01de43e96bbb94a6fcc7d6c9e1bd1e7e30ace", +"TR_de_test_language.py::test_header_trailing_data": "15ee794395d4ad28ebb80396491249c29fbab5e810ac6413a27788f0ce9d1217", "TR_de_test_language.py::test_language_is_removed_after_wipe": "f330e4d64e824ff1f20541ccedba6fbb80ccdf61a3a5197eed59789db8f3216e", "TR_de_test_language.py::test_reject_update": "c030eaa1b84ee548a68f0e20ad74201cbbeea1f09095dfafe0465020f3215a7a", "TR_de_test_language.py::test_silent_first_install[False-False]": "84a63e9be7b085d0b8ce087df8d575342a90157a52811decea69ba2083be41c1", @@ -6390,6 +6392,7 @@ "TR_en_test_language.py::test_full_language_change[en]": "a9c383b584d24c5aa9623b7955fe3e45dcf6016dbc0327a7ce9176ecb0e4d5d3", "TR_en_test_language.py::test_full_language_change[es]": "94ead6f9d0f308f60ffd135c9bbd5012a30f05b4f44fdb22286ae259bef9e205", "TR_en_test_language.py::test_full_language_change[fr]": "2f3a0e8541cc7b96dc983d4de2149e4e2b230b43e1971153ec6bc82e7dadafb8", +"TR_en_test_language.py::test_header_trailing_data": "e914c45909bd3226fbdbeae1b28507b68b87effb09df537b52adbdf87d8586e4", "TR_en_test_language.py::test_language_is_removed_after_wipe": "5363564a612486602f3e6c94cb5d18ef82c2253dfe51df4623d56b5bab920a2e", "TR_en_test_language.py::test_reject_update": "949fb112e684d3fb8a204a8ce15a202ebe9613bd3a453408138b3e54bb42e99a", "TR_en_test_language.py::test_silent_first_install[False-False]": "8c6d7a8d499e4ede3d42cb6ef67cbde9f7dd35d518bacaa538e900bf3944b250", @@ -7757,6 +7760,7 @@ "TR_es_test_language.py::test_full_language_change[en]": "5684c4f7e6ca01d85d83549d892ecc4fc0277b46dd7294d0d7ef436a2f4bbf6d", "TR_es_test_language.py::test_full_language_change[es]": "51aee9f7f7e76839471274c909bcdd2c117e3fe6d9ca634ef71f1209dcb2271a", "TR_es_test_language.py::test_full_language_change[fr]": "0f7df785e611deec165dcce914efbabb497cba640795c8b90f396c223af7f3f0", +"TR_es_test_language.py::test_header_trailing_data": "fce69490d11c51a6e3cc9d1f045e5e8b75ef3c5b4519aa702da40ea1d03a11e5", "TR_es_test_language.py::test_language_is_removed_after_wipe": "7a7d05f7feed0938e23ec6ac76133246f6dbd626969efe43b0122bb2801e4e93", "TR_es_test_language.py::test_reject_update": "72b5cc4bb1d3a1024ef5348356565e711392fc379afee08a9d4275b7d627c213", "TR_es_test_language.py::test_silent_first_install[False-False]": "fe722b1d027ca3b5af955c350722176de874b9d22446492a1b80d3f74d5bebfe", @@ -9124,6 +9128,7 @@ "TR_fr_test_language.py::test_full_language_change[en]": "5c8ccc0eb1be8baebf3d2cd0a60b022728933ac4180f27a0caa73a5b9fb0f642", "TR_fr_test_language.py::test_full_language_change[es]": "e27434b09eef1556fe6fa0b050fb2b43eed6b4f37d622b7831a5fcbcde3f72bd", "TR_fr_test_language.py::test_full_language_change[fr]": "7fae72778d7111b0d7746ce3fdfdae724415f651b2c3e195da55dc3cf6e24f8e", +"TR_fr_test_language.py::test_header_trailing_data": "68923fb1c4fc87822131d1c543c1ccb1f730f56d7dc0ae81a01109d6b8cb3a7f", "TR_fr_test_language.py::test_language_is_removed_after_wipe": "9c12ba731cef7dd8a2fbb421aa328af48ed383b9d4ea4edb6cfbe6bd7a594115", "TR_fr_test_language.py::test_reject_update": "4c1d851a4f7ca6075e71d096a4b124b31f8ff280d609cc2495ded9750f057b51", "TR_fr_test_language.py::test_silent_first_install[False-False]": "79baf3cf0b204f265a80ce571552b1fb082aeb72cc37d515b6682365a6ebeae4", @@ -10798,6 +10803,7 @@ "TT_cs_test_language.py::test_full_language_change[en]": "4221be0ec3ac6b31d53878bd3cf2d216b962b06c6bd793cbc8f4228594d391f5", "TT_cs_test_language.py::test_full_language_change[es]": "1d021e60c0a5a25950064ab3159df74bf477bec6db1d05a62568dd195b7f6a0a", "TT_cs_test_language.py::test_full_language_change[fr]": "5b6297ad7b03664e18a95b8eb32ff4f0fd76f827da64559e09815fa506812440", +"TT_cs_test_language.py::test_header_trailing_data": "919fd0107366fe4dab3b7216a758a24ddb22a9c61ba669e05892df43a08d6b38", "TT_cs_test_language.py::test_language_is_removed_after_wipe": "a3ae02a5a95dbfa4ffde27c66ab3b5a766aa0e84e04c64504c19a3ae432d0e8b", "TT_cs_test_language.py::test_reject_update": "baabea339f79af37b0184349a1d1e360cbbf111fc8fe8c7bf89f6ee8b6091cbb", "TT_cs_test_language.py::test_silent_first_install[False-False]": "b8494f22dfd7426af61780d585cedbdfbdd20c65721cc50e599e6f0c97aec1cb", @@ -12245,6 +12251,7 @@ "TT_de_test_language.py::test_full_language_change[en]": "4471ecae299a6e26d3708a189c9cfcb706f21ef21639a978a04c28e6c478f9c4", "TT_de_test_language.py::test_full_language_change[es]": "ebe595cee2832bd1e7ad4ef6476ff9dba50ccd26f3119c5cda9c17b1dd178ae4", "TT_de_test_language.py::test_full_language_change[fr]": "256177588435bf75d7bb339e835a6e79f8d10314f155784047b9d5a77a5c5e72", +"TT_de_test_language.py::test_header_trailing_data": "b7c2dcfbac8e5261d83ebac9fba426ce682af350c7b2aa44e230ef31749180cf", "TT_de_test_language.py::test_language_is_removed_after_wipe": "5b9f5817ba4e243d41262887aa338bb674f700ce47e1b50bc564cfd665876799", "TT_de_test_language.py::test_reject_update": "adef723d293c68592689b4fafbe87e6811656e6ea962484474594ce8f2407b4b", "TT_de_test_language.py::test_silent_first_install[False-False]": "629c908f9d1d76b1248297c5a2eb9ee4933d54c53003329599312d6f292d4c7d", @@ -13692,6 +13699,7 @@ "TT_en_test_language.py::test_full_language_change[en]": "5f6cec419aad5e5658f6fda45c2cd40fa4581823e7f9f0c4199970cd179bfd4e", "TT_en_test_language.py::test_full_language_change[es]": "fcb472f8786ab55cc7b90450a002165fd74ed88edc0d41a0dffd741b801d7f0b", "TT_en_test_language.py::test_full_language_change[fr]": "a6b00695cb76f4fcc7197d37df49c3b1997da6ed23f2c21330d30e0f28dc910d", +"TT_en_test_language.py::test_header_trailing_data": "83ef1fdc5cc38aa181c9bf68099ed5ba827a8cf9fcc6bf6a7bc5c9d1ac6a9d78", "TT_en_test_language.py::test_language_is_removed_after_wipe": "20955fc2d8ae93c616be7041440c1e86a6a92e3235b352abdf0f17d95319d600", "TT_en_test_language.py::test_reject_update": "78b8f16e00c5d653a7d5c0929d21ae8ae1c76798fe28f0eb6edee8e2ee8b0202", "TT_en_test_language.py::test_silent_first_install[False-False]": "bbd64861dce4334f1d4a49cdccf981c854b72fe6807adfa516d115337eb60a36", @@ -15157,6 +15165,7 @@ "TT_es_test_language.py::test_full_language_change[en]": "b156bab790f73a90410c6951b8d1e0f1cafc9b1f7c33b0d90cc6fde86583c093", "TT_es_test_language.py::test_full_language_change[es]": "dc724987f4e89000676d39cda877fd25cb2d8d1360eb28be9683b19b48a7aa0f", "TT_es_test_language.py::test_full_language_change[fr]": "a8d92d89b104b2fc3ee65e17d870366fd22fa910d2971d1c61319078a15244bc", +"TT_es_test_language.py::test_header_trailing_data": "d3928eb02ac97f9fd3a62919bb14fc7f1c6a8aaaffba842518a32e74a2a754cb", "TT_es_test_language.py::test_language_is_removed_after_wipe": "6a92f98a10478ddc916f0b8f6c56b13cae1f458a9ad86eb6c8f46a9033abcdec", "TT_es_test_language.py::test_reject_update": "107634fbdacc72337abd7de1291904e6297bf5dd9551163780a1438b6d965949", "TT_es_test_language.py::test_silent_first_install[False-False]": "b307450f1f7e6118118b631c8354e9acb89f90f5755294ebb45b610ee8fc23c2", @@ -16604,6 +16613,7 @@ "TT_fr_test_language.py::test_full_language_change[en]": "f77bf50157ba8e718b35af18003b8ebd296c076949cb138abba570d04159ce46", "TT_fr_test_language.py::test_full_language_change[es]": "dee01837c5deb4758a4fdcc1c10da654bd7da2917d371b2188e01dcce6574458", "TT_fr_test_language.py::test_full_language_change[fr]": "f59be182fa1ff0bfb9230b69a49dabfed30394618e2eaf11597c8a109a7bab95", +"TT_fr_test_language.py::test_header_trailing_data": "abf21ee323be4a9fe145d080b404778daf06f4148a43bfa2528856cbb4310a9b", "TT_fr_test_language.py::test_language_is_removed_after_wipe": "a474ebb565e9e2fc01647fe2ae739519f25807562abe757ac55d20814b3458af", "TT_fr_test_language.py::test_reject_update": "1ea4e3f645e5d788714b61525c0eee446a306f2844fec383460e45574f9a5de5", "TT_fr_test_language.py::test_silent_first_install[False-False]": "d0046d29c419e87c0f3881d7c9308c9621dc111a6b5a914eb8bd63266a7d7b91",