diff --git a/.github/workflows/codeql_checks.yml b/.github/workflows/codeql_checks.yml index fb95064..acbc6b4 100644 --- a/.github/workflows/codeql_checks.yml +++ b/.github/workflows/codeql_checks.yml @@ -18,7 +18,7 @@ jobs: name: Analyse strategy: matrix: - sdk: [ "$NANOS_SDK", "$NANOX_SDK", "$NANOSP_SDK", "$STAX_SDK" ] + sdk: [ "$NANOS_SDK", "$NANOX_SDK", "$NANOSP_SDK", "$STAX_SDK", "$FLEX_SDK" ] #'cpp' covers C and C++ language: [ 'cpp' ] runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index 90076c4..08ff4f0 100644 --- a/Makefile +++ b/Makefile @@ -29,8 +29,8 @@ APPNAME = OpenPGP # Application version APPVERSION_M = 2 -APPVERSION_N = 2 -APPVERSION_P = 2 +APPVERSION_N = 3 +APPVERSION_P = 0 APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)" SPECVERSION:="3.3.1" @@ -50,6 +50,7 @@ ICON_NANOS = icons/gpg_16px.gif ICON_NANOX = icons/gpg_14px.gif ICON_NANOSP = icons/gpg_14px.gif ICON_STAX = icons/gpg_32px.gif +ICON_FLEX = icons/gpg_40px.gif # Application allowed derivation curves. # Possibles curves are: secp256k1, secp256r1, ed25519 and bls12381g1 @@ -124,6 +125,8 @@ DEFINES += HAVE_USB_CLASS_CCID DEFINES += HAVE_RSA # Watchdog issue causing the device reset with long prime number computation # DEFINES += WITH_SUPPORT_RSA4096 +# Limitation (maybe due to openpgp itself): no support of DEC operation with cv25519 +DEFINES += NO_DECRYPT_cv25519 ifeq ($(TARGET_NAME),TARGET_NANOS) DEFINES += HAVE_UX_LEGACY diff --git a/README.md b/README.md index 5c5a959..a773fae 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,7 @@ You can choose which device to compile and load for by setting the `BOLOS_SDK` e - `BOLOS_SDK=$NANOX_SDK` - `BOLOS_SDK=$NANOSP_SDK` - `BOLOS_SDK=$STAX_SDK` +- `BOLOS_SDK=$FLEX_SDK` ### Loading on a physical device diff --git a/doc/developer/quick-test.md b/doc/developer/quick-test.md index 1e3d892..732b023 100644 --- a/doc/developer/quick-test.md +++ b/doc/developer/quick-test.md @@ -82,6 +82,7 @@ opensc-pkcs11: opensc-pkcs11.so user-pin-initialized protected-authentication-path token-initialized +``` Check the installation of CCID driver and more particularly its device config: @@ -103,11 +104,14 @@ Usage: ./manual.sh Options: - -c : Requested command + -c : Requested command + -e : Expert mode -v : Verbose mode -h : Displays this help ``` +> Note: This script allows to automatically use a test gpg directory, like setting `GNUGPGHOME` + The `init` command allows to prepare a local `gnupg` home directory, with the default minimal config file for *scdaemon*. For further investigations, you can also add in the file `manual-tests/gnupg/scdaemon.conf` the following lines: @@ -117,6 +121,16 @@ debug 11 log-file /tmp/scdaemon.log ``` +The `reset` command just allows to kill running *scdaemon* or *gpg-agent* processes. Useful to start clean tests. + +The `card` command is a shortcut to the `gpg --card-edit` command. + +The `default` command, used **after** keys creation, allows to configure the default keys for signature and decryption. +The information is written in the file `manual-tests/gnupg/gpg.conf`. +This step is very useful when playing with backup/restore to ensure the default key will be found. + +The other commands are shortcuts allowing basic operations to test the key. + ## Step 3: Verify the card status and the pin code Launch the Application on the device. diff --git a/doc/user/0001-plist.patch b/doc/user/0001-plist.patch index 73ca1ad..b7935ed 100644 --- a/doc/user/0001-plist.patch +++ b/doc/user/0001-plist.patch @@ -5,6 +5,7 @@ 0x2C97 0x2C97 + 0x2C97 ++ 0x2C97 + 0x2C97 0x17EF 0x17EF @@ -19,6 +20,7 @@ + 0x4009 + 0x5009 + 0x6009 ++ 0x7009 0x6007 0x6055 0x6111 @@ -28,6 +30,7 @@ Ledger Nano X + Ledger Nano S Plus + Ledger Stax ++ Ledger Flex Lenovo Lenovo USB Smartcard Keyboard Lenovo Lenovo USB Smartcard Keyboard Lenovo Lenovo Smartcard Wired Keyboard II diff --git a/doc/user/app-openpgp.pdf b/doc/user/app-openpgp.pdf index 5e2ea57..15c9108 100644 Binary files a/doc/user/app-openpgp.pdf and b/doc/user/app-openpgp.pdf differ diff --git a/doc/user/app-openpgp.rst b/doc/user/app-openpgp.rst index 48ac27d..a0a06fb 100644 --- a/doc/user/app-openpgp.rst +++ b/doc/user/app-openpgp.rst @@ -125,6 +125,12 @@ Thus, you must ensure (or add): - ifdProductID: 0x6009 - ifdFriendlyName: Ledger Stax +- for Flex: + + - ifdVendorID: 0x2C97 + - ifdProductID: 0x7009 + - ifdFriendlyName: Ledger Flex + Notes: - The 3 entry nodes must be added for each device. It can be easier to add new ones at the end of each list. @@ -197,7 +203,7 @@ with: Select Slot ------------- -For Nanos, this menu is only available on *XL* version. It is available on all other devices. +This menu is not available on Nanos, limited to a single slot. It is available on all other devices. A Slot is a set of 3 key pairs *Signature, Decryption, Authentication* as defined by gnupg specification. @@ -414,7 +420,7 @@ Configuration In order to use a Ledger device with gpg it is needed to explicitly setup the reader and the delegated PIN support. -Edit the file ``~/.gnupg/scdaemon.conf`` and add the following lines: +Create or edit the file ``~/.gnupg/scdaemon.conf`` and add the following lines: | ``reader-port "Ledger Token"`` | ``allow-admin`` @@ -1137,7 +1143,7 @@ Finally run the following command: | ``python3 -m gpgcard.gpgcli --pinpad --set-template ed255519:cv25519:ed255519 --set-fingerprints`` | ``'2C688345BDDA0EDFB24DB4FB8451AAF7D43D1095:DF157BD4AC3BD1EE991099C80953D871FC4B9EA4:CEC59AE6A76614BC3C6D37D9C5A8FB078520ABBB'`` - | ``--set-serial 'FD6C11BE' --seed-key`` + | ``--serial 'FD6C11BE' --seed-key`` Restore lost Keyring ~~~~~~~~~~~~~~~~~~~~ @@ -1576,7 +1582,7 @@ To *restore* a backup, simply use the tool like this: | ``$ ./backup.py --restore --adm-pin 12345678 --user-pin 123456 --seed-key`` | ``Connect to card 'Ledger'...`` - | ``Configuration saved in file 'gpg_backup'.`` + | ``Configuration restored from file 'gpg_backup'.`` Annexes ======= diff --git a/icons/gpg_40px.gif b/icons/gpg_40px.gif new file mode 100644 index 0000000..c83dae5 Binary files /dev/null and b/icons/gpg_40px.gif differ diff --git a/ledger_app.toml b/ledger_app.toml index e557cc8..27f2fad 100644 --- a/ledger_app.toml +++ b/ledger_app.toml @@ -1,7 +1,7 @@ [app] build_directory = "./" sdk = "C" -devices = ["nanos", "nanox", "nanos+", "stax"] +devices = ["nanos", "nanox", "nanos+", "stax", "flex"] [tests] unit_directory = "./unit-tests/" diff --git a/manual-tests/manual.sh b/manual-tests/manual.sh index 082cd9b..6c4dbf9 100755 --- a/manual-tests/manual.sh +++ b/manual-tests/manual.sh @@ -24,8 +24,8 @@ help() { echo echo "Options:" echo - echo " -c : Requested command" - echo " -e : Expert mode mode" + echo " -c : Requested command" + echo " -e : Expert mode" echo " -v : Verbose mode" echo " -h : Displays this help" echo @@ -42,6 +42,30 @@ reset() { killall scdaemon gpg-agent 2>/dev/null } +#=============================================================================== +# +# default - Set default key in conf file +# +#=============================================================================== +default() { + dir=$(basename "${gnupg_home_dir}") + if [[ ! -d "${dir}" ]]; then + mkdir "${dir}" + chmod 700 "${dir}" + fi + + recipient=$(gpg --homedir "${gnupg_home_dir}" --card-status | grep "General key info" | awk '{print $NF}') + + if [[ ${recipient} =~ "none" ]]; then + read -r -p "Enter default key name: " recipient + fi + + { + echo "default-key ${recipient}" + echo "default-recipient ${recipient}" + } > "${dir}/gpg.conf" +} + #=============================================================================== # # init - Init the gnupg config, start from an empty keyring @@ -93,19 +117,15 @@ card() { # #=============================================================================== encrypt() { - local recipient="" local verbose_mode="" + reset rm -fr foo* echo CLEAR > foo.txt [[ ${VERBOSE} == true ]] && verbose_mode="--verbose" - recipient=$(gpg --homedir "${gnupg_home_dir}" --card-status | grep "General key info" | awk '{print $NF}') - - echo "Encrypt with recipient '${recipient}'" - - gpg --homedir "${gnupg_home_dir}" ${verbose_mode} --encrypt --recipient "${recipient}" foo.txt + gpg --homedir "${gnupg_home_dir}" ${verbose_mode} --encrypt foo.txt } #=============================================================================== @@ -123,8 +143,7 @@ decrypt() { gpg --homedir "${gnupg_home_dir}" ${verbose_mode} --decrypt foo.txt.gpg > foo_dec.txt # Check with original clear file - diff foo.txt foo_dec.txt >/dev/null - if [[ $? -eq 0 ]]; then + if diff foo.txt foo_dec.txt >/dev/null; then echo "Success !" else echo "Decryption error!" @@ -180,7 +199,7 @@ while getopts ":c:evh" opt; do c) case ${OPTARG} in - init|reset|card|encrypt|decrypt|sign|verify) + init|reset|card|encrypt|decrypt|sign|verify|default) CMD=${OPTARG} ;; *) diff --git a/pytools/gpgapp/gpgcard.py b/pytools/gpgapp/gpgcard.py index 897f5b4..ce8df05 100644 --- a/pytools/gpgapp/gpgcard.py +++ b/pytools/gpgapp/gpgcard.py @@ -1010,6 +1010,7 @@ def asymmetric_key(self, key: str, action: str) -> dict: op = KEY_OPERATIONS[action] attributes = None + b_key: int = 0 if key == KeyTypes.KEY_SIG: attributes = self.data.sig.attribute b_key = DataObject.DO_SIG_KEY @@ -1167,6 +1168,7 @@ def _set_key_date_now(self, key: str) -> None: dt = datetime.utcnow().replace(microsecond=0) bdate = int(dt.timestamp()).to_bytes(4, "big") + tag: Optional[DataObject] = None if key == KeyTypes.KEY_SIG: self.data.sig.date = dt tag = DataObject.DO_DATES_WR_SIG @@ -1176,7 +1178,8 @@ def _set_key_date_now(self, key: str) -> None: elif key == KeyTypes.KEY_DEC: self.data.dec.date = dt tag = DataObject.DO_DATES_WR_DEC - self._put_data(tag, bdate) + if tag: + self._put_data(tag, bdate) def _decode_tlv(self, tlv: bytes) -> dict: diff --git a/src/gpg_data.c b/src/gpg_data.c index 436bde8..b69ebec 100644 --- a/src/gpg_data.c +++ b/src/gpg_data.c @@ -264,6 +264,9 @@ int gpg_apdu_put_data(unsigned int ref) { cx_err_t error = CX_INTERNAL_ERROR; unsigned int pkey_size = 0; unsigned int ksz, curve; +#ifdef NO_DECRYPT_cv25519 + bool decKey = false; +#endif G_gpg_vstate.DO_current = ref; @@ -655,6 +658,9 @@ int gpg_apdu_put_data(unsigned int ref) { case 0xC2: ptr_l = &G_gpg_vstate.kslot->dec.attributes.length; ptr_v = G_gpg_vstate.kslot->dec.attributes.value; +#ifdef NO_DECRYPT_cv25519 + decKey = true; +#endif goto WRITE_ATTRIBUTES; case 0xC3: ptr_l = &G_gpg_vstate.kslot->aut.attributes.length; @@ -679,6 +685,12 @@ int gpg_apdu_put_data(unsigned int ref) { case KEY_ID_EDDSA: curve = gpg_oid2curve(G_gpg_vstate.work.io_buffer + 1, G_gpg_vstate.io_length - 1); +#ifdef NO_DECRYPT_cv25519 + if ((decKey) && (curve == CX_CURVE_Curve25519)) { + sw = SW_WRONG_DATA; + break; + } +#endif if (curve == CX_CURVE_NONE) { sw = SW_WRONG_DATA; } else { diff --git a/src/gpg_gen.c b/src/gpg_gen.c index bd9b451..8dfec45 100644 --- a/src/gpg_gen.c +++ b/src/gpg_gen.c @@ -114,11 +114,9 @@ static int gpg_gen_rsa_kyey(gpg_key_t *keygpg, uint8_t *name) { case 3072 / 8: pkey_size = sizeof(cx_rsa_3072_private_key_t); break; -#ifdef WITH_SUPPORT_RSA4096 case 4096 / 8: pkey_size = sizeof(cx_rsa_4096_private_key_t); break; -#endif default: break; } @@ -195,14 +193,12 @@ static int gpg_read_rsa_kyey(gpg_key_t *keygpg) { } gpg_io_insert_tlv(0x81, ksz, (unsigned char *) &keygpg->priv_key.rsa3072.n); break; -#ifdef WITH_SUPPORT_RSA4096 case 4096 / 8: if (keygpg->priv_key.rsa4096.size == 0) { return SW_REFERENCED_DATA_NOT_FOUND; } gpg_io_insert_tlv(0x81, ksz, (unsigned char *) &keygpg->priv_key.rsa4096.n); break; -#endif default: return SW_REFERENCED_DATA_NOT_FOUND; } diff --git a/src/gpg_pin.c b/src/gpg_pin.c index 7f74d3c..27baaaa 100644 --- a/src/gpg_pin.c +++ b/src/gpg_pin.c @@ -319,7 +319,7 @@ int gpg_apdu_change_ref_data() { } /** - * APDU handler to Reste PinCode or Counter + * APDU handler to Reset PinCode or Counter * * @return Status Word * diff --git a/src/gpg_pso.c b/src/gpg_pso.c index 360c720..ac1f5c8 100644 --- a/src/gpg_pso.c +++ b/src/gpg_pso.c @@ -94,11 +94,9 @@ static int gpg_sign(gpg_key_t *sigkey) { case 3072 / 8: rsa_key = (cx_rsa_private_key_t *) &sigkey->priv_key.rsa3072; break; -#ifdef WITH_SUPPORT_RSA4096 case 4096 / 8: rsa_key = (cx_rsa_private_key_t *) &sigkey->priv_key.rsa4096; break; -#endif default: break; } @@ -286,12 +284,10 @@ int gpg_apdu_pso() { rsa_key = (cx_rsa_private_key_t *) &G_gpg_vstate.mse_dec->priv_key.rsa3072; break; -#ifdef WITH_SUPPORT_RSA4096 case 4096 / 8: rsa_key = (cx_rsa_private_key_t *) &G_gpg_vstate.mse_dec->priv_key.rsa4096; break; -#endif } if ((rsa_key == NULL) || (rsa_key->size != ksz)) { @@ -339,43 +335,71 @@ int gpg_apdu_pso() { break; } ecfp_key = &G_gpg_vstate.mse_dec->priv_key.ecfp; + curve = gpg_oid2curve(G_gpg_vstate.mse_dec->attributes.value + 1, + G_gpg_vstate.mse_dec->attributes.length - 1); + if (ecfp_key->curve != curve) { + error = SW_CONDITIONS_NOT_SATISFIED; + break; + } + // Check APDU content tags gpg_io_fetch_l(&l); gpg_io_fetch_tl(&t, &l); + // TAG 0x7f49 announces a Public Key DO if (t != 0x7f49) { error = SW_WRONG_DATA; break; } gpg_io_fetch_tl(&t, &l); + // TAG 0x86 announces an External Public Key (with its length) if (t != 0x86) { error = SW_WRONG_DATA; break; } - curve = gpg_oid2curve(G_gpg_vstate.mse_dec->attributes.value + 1, - G_gpg_vstate.mse_dec->attributes.length - 1); - if (ecfp_key->curve != curve) { - error = SW_CONDITIONS_NOT_SATISFIED; - break; - } if (curve == CX_CURVE_Curve25519) { - for (cnt = 0; cnt <= 31; cnt++) { - G_gpg_vstate.work.io_buffer[512 + cnt] = - (G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset)[31 - cnt]; + uint8_t raw_public_key[65]; + uint8_t secret[32]; + cx_ecpoint_t public_point; + uint8_t i; + + if (l != 32) { + PRINTF("[PSO] - PSO:DEC:ECDH - Wrong Ext Pub Key size %d\n", l); + error = SW_WRONG_DATA; + break; } - G_gpg_vstate.work.io_buffer[511] = 0x02; - CX_CHECK(cx_ecdh_no_throw(ecfp_key, - CX_ECDH_X, - G_gpg_vstate.work.io_buffer + 511, - 65, - G_gpg_vstate.work.io_buffer + 256, - 160)); + CX_CHECK(cx_ecdomain_parameters_length(ecfp_key->curve, &ksz)); + if (ksz != 32) { + PRINTF("[PSO] - PSO:DEC:ECDH - Wrong curve Key size %d\n", ksz); + error = SW_WRONG_DATA; + break; + } + // Reverse key bytes order + for (i = 0; i <= 31; i++) { + raw_public_key[i] = + (G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset)[31 - i]; + } - for (cnt = 0; cnt <= 31; cnt++) { - G_gpg_vstate.work.io_buffer[128 + cnt] = - G_gpg_vstate.work.io_buffer[287 - cnt]; + CX_CHECK(cx_bn_lock(32, 0)); + CX_CHECK(cx_ecpoint_alloc(&public_point, CX_CURVE_Curve25519)); + CX_CHECK(cx_ecpoint_decompress(&public_point, raw_public_key, 32, 0)); + CX_CHECK(cx_ecpoint_export(&public_point, + raw_public_key + 1, + 32, + raw_public_key + 1 + 32, + 32)); + CX_CHECK(cx_bn_unlock()); + raw_public_key[0] = 0x04; + CX_CHECK(cx_ecdh_no_throw(ecfp_key, + CX_ECDH_X, + raw_public_key, + sizeof(raw_public_key), + secret, + sizeof(secret))); + // Reverse key bytes order + for (i = 0; i <= 31; i++) { + G_gpg_vstate.work.io_buffer[128 + i] = secret[31 - i]; } - ksz = 32; } else { CX_CHECK( cx_ecdh_no_throw(ecfp_key, diff --git a/src/gpg_types.h b/src/gpg_types.h index 1a693d8..4e98301 100644 --- a/src/gpg_types.h +++ b/src/gpg_types.h @@ -90,9 +90,7 @@ typedef struct gpg_key_s { cx_rsa_private_key_t rsa; cx_rsa_2048_private_key_t rsa2048; cx_rsa_3072_private_key_t rsa3072; -#ifdef WITH_SUPPORT_RSA4096 cx_rsa_4096_private_key_t rsa4096; -#endif cx_ecfp_private_key_t ecfp; cx_ecfp_256_private_key_t ecfp256; cx_ecfp_384_private_key_t ecfp384; @@ -222,17 +220,13 @@ struct gpg_v_state_s { cx_rsa_public_key_t public; cx_rsa_2048_public_key_t public2048; cx_rsa_3072_public_key_t public3072; -#ifdef WITH_SUPPORT_RSA4096 cx_rsa_4096_public_key_t public4096; -#endif }; union { cx_rsa_private_key_t private; cx_rsa_2048_private_key_t private2048; cx_rsa_3072_private_key_t private3072; -#ifdef WITH_SUPPORT_RSA4096 cx_rsa_4096_private_key_t private4096; -#endif }; } rsa; diff --git a/src/gpg_ux.c b/src/gpg_ux.c index eca47c5..fc9e141 100644 --- a/src/gpg_ux.c +++ b/src/gpg_ux.c @@ -49,5 +49,4 @@ void app_reset(void) { nvm_write((void*) (N_gpg_pstate->magic), magic, MAGIC_LENGTH); gpg_init(); ui_CCID_reset(); - ui_init(); } diff --git a/src/gpg_ux_nanos.c b/src/gpg_ux_nanos.c index 4c31f23..d0a1328 100644 --- a/src/gpg_ux_nanos.c +++ b/src/gpg_ux_nanos.c @@ -592,13 +592,20 @@ unsigned int ui_pinentry_action_button(unsigned int button_mask, unsigned int bu } /* ------------------------------- template UX ------------------------------- */ +#ifdef NO_DECRYPT_cv25519 +void ui_menu_template_display_type(unsigned int value); +#endif const ux_menu_entry_t ui_menu_tmpl_key[]; const ux_menu_entry_t ui_menu_tmpl_type[]; const ux_menu_entry_t ui_menu_template[] = { {ui_menu_tmpl_key, NULL, -1, NULL, "Choose key...", NULL, 0, 0}, +#ifdef NO_DECRYPT_cv25519 + {NULL, ui_menu_template_display_type, -1, NULL, "Choose type...", NULL, 0, 0}, +#else {ui_menu_tmpl_type, NULL, -1, NULL, "Choose type...", NULL, 0, 0}, +#endif {NULL, ui_menu_tmpl_set_action, -1, NULL, "Set template", NULL, 0, 0}, {ui_menu_settings, NULL, 0, &C_icon_back, "Back", NULL, 61, 40}, UX_MENU_END}; @@ -622,6 +629,19 @@ const ux_menu_entry_t ui_menu_tmpl_type[] = { {ui_menu_template, NULL, 0, &C_icon_back, "Back", NULL, 61, 40}, UX_MENU_END}; +#ifdef NO_DECRYPT_cv25519 +const ux_menu_entry_t ui_menu_tmpl_Dectype[] = { + {NULL, ui_menu_tmpl_type_action, 2048, NULL, LABEL_RSA2048, NULL, 0, 0}, + {NULL, ui_menu_tmpl_type_action, 3072, NULL, LABEL_RSA3072, NULL, 0, 0}, +#ifdef WITH_SUPPORT_RSA4096 + {NULL, ui_menu_tmpl_type_action, 4096, NULL, LABEL_RSA4096, NULL, 0, 0}, +#endif + {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256K1, NULL, LABEL_SECP256K1, NULL, 0, 0}, + {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256R1, NULL, LABEL_SECP256R1, NULL, 0, 0}, + {ui_menu_template, NULL, 0, &C_icon_back, "Back", NULL, 61, 40}, + UX_MENU_END}; +#endif + /** * Template page display preparation callback * @@ -671,7 +691,17 @@ const bagl_element_t *ui_menu_template_predisplay(const ux_menu_entry_t *entry, snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_SECP256R1); break; case CX_CURVE_Ed25519: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_Ed25519); +#ifdef NO_DECRYPT_cv25519 + if (G_gpg_vstate.ux_key == 2) { + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Choose type..."); + } else +#endif + { + snprintf(G_gpg_vstate.menu, + sizeof(G_gpg_vstate.menu), + " %s", + LABEL_Ed25519); + } break; default: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Choose type..."); @@ -692,7 +722,16 @@ const bagl_element_t *ui_menu_template_predisplay(const ux_menu_entry_t *entry, void ui_menu_template_display(unsigned int value) { UX_MENU_DISPLAY(value, ui_menu_template, ui_menu_template_predisplay); } - +#ifdef NO_DECRYPT_cv25519 +void ui_menu_template_display_type(unsigned int value) { + UNUSED(value); + if (G_gpg_vstate.ux_key == 2) { + UX_MENU_DISPLAY(0, ui_menu_tmpl_Dectype, ui_menu_template_predisplay); + } else { + UX_MENU_DISPLAY(0, ui_menu_tmpl_type, ui_menu_template_predisplay); + } +} +#endif /** * Template Action callback * @@ -1141,6 +1180,7 @@ void ui_menu_reset_action(unsigned int value) { UNUSED(value); app_reset(); + ui_init(); } /* ------------------------------- SETTINGS UX ------------------------------- */ @@ -1158,13 +1198,9 @@ const ux_menu_entry_t ui_menu_settings[] = { const ux_menu_entry_t ui_menu_info[] = { {NULL, NULL, -1, NULL, "OpenPGP Card", NULL, 0, 0}, - {NULL, NULL, -1, NULL, "(c) Ledger SAS", NULL, 0, 0}, + {NULL, NULL, -1, NULL, "Version " APPVERSION, NULL, 0, 0}, {NULL, NULL, -1, NULL, "Spec " XSTR(SPEC_VERSION), NULL, 0, 0}, -#ifdef HAVE_PRINTF - {NULL, NULL, -1, NULL, "[DBG] App " XSTR(APPVERSION), NULL, 0, 0}, -#else - {NULL, NULL, -1, NULL, "App " XSTR(APPVERSION), NULL, 0, 0}, -#endif + {NULL, NULL, -1, NULL, "(c) Ledger SAS", NULL, 0, 0}, {NULL, ui_menu_main_display, 3, &C_icon_back, "Back", NULL, 61, 40}, UX_MENU_END}; diff --git a/src/gpg_ux_nanox.c b/src/gpg_ux_nanox.c index 8280098..2928b70 100644 --- a/src/gpg_ux_nanox.c +++ b/src/gpg_ux_nanox.c @@ -570,6 +570,23 @@ const unsigned int tmpl_type_getter_values_map[] = {2048, CX_CURVE_SECP256K1, CX_CURVE_SECP256R1, CX_CURVE_Ed25519}; +#ifdef NO_DECRYPT_cv25519 +const char *const tmpl_type_getter_Decvalues[] = {LABEL_RSA2048, + LABEL_RSA3072, +#ifdef WITH_SUPPORT_RSA4096 + LABEL_RSA4096, +#endif + LABEL_SECP256K1, + LABEL_SECP256R1}; + +const unsigned int tmpl_type_getter_Decvalues_map[] = {2048, + 3072, +#ifdef WITH_SUPPORT_RSA4096 + 4096, +#endif + CX_CURVE_SECP256K1, + CX_CURVE_SECP256R1}; +#endif /** * Helper to get the key type @@ -580,8 +597,17 @@ const unsigned int tmpl_type_getter_values_map[] = {2048, * */ static const char *tmpl_type_getter(unsigned int idx) { - if (idx < ARRAYLEN(tmpl_type_getter_values)) { - return tmpl_type_getter_values[idx]; +#ifdef NO_DECRYPT_cv25519 + if (G_gpg_vstate.ux_key == 2) { + if (idx < ARRAYLEN(tmpl_type_getter_Decvalues)) { + return tmpl_type_getter_Decvalues[idx]; + } + } else +#endif + { + if (idx < ARRAYLEN(tmpl_type_getter_values)) { + return tmpl_type_getter_values[idx]; + } } return NULL; } @@ -593,10 +619,21 @@ static const char *tmpl_type_getter(unsigned int idx) { * */ static void tmpl_type_selector(unsigned int idx) { - if (idx < ARRAYLEN(tmpl_type_getter_values)) { - idx = tmpl_type_getter_values_map[idx]; - } else { - idx = 0; +#ifdef NO_DECRYPT_cv25519 + if (G_gpg_vstate.ux_key == 2) { + if (idx < ARRAYLEN(tmpl_type_getter_Decvalues)) { + idx = tmpl_type_getter_Decvalues_map[idx]; + } else { + idx = 0; + } + } else +#endif + { + if (idx < ARRAYLEN(tmpl_type_getter_values)) { + idx = tmpl_type_getter_values_map[idx]; + } else { + idx = 0; + } } G_gpg_vstate.ux_type = idx; ui_menu_template_display(1); @@ -684,7 +721,14 @@ void ui_menu_template_predisplay() { snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_SECP256R1); break; case CX_CURVE_Ed25519: - snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_Ed25519); +#ifdef NO_DECRYPT_cv25519 + if (G_gpg_vstate.ux_key == 2) { + snprintf(KEY_TYPE, sizeof(KEY_TYPE), "Choose type..."); + } else +#endif + { + snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_Ed25519); + } break; default: snprintf(KEY_TYPE, sizeof(KEY_TYPE), "Choose type..."); @@ -781,7 +825,7 @@ void ui_menu_tmpl_set_action(unsigned int value) { if (dest != NULL) { nvm_write(dest, NULL, sizeof(gpg_key_t)); nvm_write(&dest->attributes, &attributes, sizeof(attributes)); - ui_menu_template_display(1); + ui_menu_template_display(0); } else { ui_info(INVALID_SELECTION, TEMPLATE_KEY); } @@ -1195,6 +1239,7 @@ void ui_menu_reset_action(unsigned int value) { UNUSED(value); app_reset(); + ui_init(); } /* ------------------------------- SETTINGS UX ------------------------------- */ @@ -1365,13 +1410,9 @@ UX_STEP_NOCB(ux_menu_info_1_step, bnnn, { "OpenPGP Card", - "(c) Ledger SAS", + "Version " APPVERSION, "Spec " XSTR(SPEC_VERSION), -#ifdef HAVE_PRINTF - "[DBG] App " XSTR(APPVERSION), -#else - "App " XSTR(APPVERSION), -#endif + "(c) Ledger SAS", }); UX_STEP_CB(ux_menu_info_2_step, diff --git a/src/gpg_ux_nbgl.c b/src/gpg_ux_nbgl.c index 4a90294..b65c22a 100644 --- a/src/gpg_ux_nbgl.c +++ b/src/gpg_ux_nbgl.c @@ -17,7 +17,7 @@ *****************************************************************************/ #include "bolos_target.h" -#if defined(HAVE_NBGL) && defined(TARGET_STAX) +#if defined(HAVE_NBGL) && (defined(TARGET_STAX) || defined(TARGET_FLEX)) #include "os.h" #include "glyphs.h" @@ -31,15 +31,16 @@ /* ----------------------------------------------------------------------- */ /* --- NBGL UI layout --- */ /* ----------------------------------------------------------------------- */ -static void ui_menu_settings(); static void ui_menu_slot_action(); -static void settings_ctrl_cb(int token, uint8_t index); static void ui_settings_template(void); static void ui_settings_seed(void); static void ui_settings_pin(void); +static void ui_settings_uif(void); +static void ui_reset(void); // context for background and modal pages static nbgl_layout_t layoutCtx = {0}; +static uint8_t setting_initPage; /* ------------------------------- Helpers UX ------------------------------- */ @@ -76,7 +77,7 @@ static void ui_setting_header(const char* title, explicit_bzero(&bar, sizeof(nbgl_layoutBar_t)); bar.text = PIC(title); - bar.iconLeft = &C_leftArrow32px; + bar.iconLeft = &LEFT_ARROW_ICON; bar.token = back_token; bar.centered = true; bar.inactive = false; @@ -89,11 +90,48 @@ static void ui_setting_header(const char* title, // ----------------------- HOME PAGE ------------------------- // ----------------------------------------------------------- +enum { + TOKEN_SETTINGS_TEMPLATE = FIRST_USER_TOKEN, + TOKEN_SETTINGS_SEED, + TOKEN_SETTINGS_PIN, + TOKEN_SETTINGS_UIF, + TOKEN_SETTINGS_RESET, +}; + /** - * home page definition + * Settings callback + * + * @param[in] token button Id pressed + * @param[in] index widget index on the page * */ -void ui_init(void) { +static void controlsCallback(int token, uint8_t index, int page) { + UNUSED(index); + setting_initPage = page; + switch (token) { + case TOKEN_SETTINGS_TEMPLATE: + ui_settings_template(); + break; + case TOKEN_SETTINGS_SEED: + ui_settings_seed(); + break; + case TOKEN_SETTINGS_PIN: + ui_settings_pin(); + break; + case TOKEN_SETTINGS_UIF: + ui_settings_uif(); + break; + case TOKEN_SETTINGS_RESET: + ui_reset(); + break; + } +} + +/** + * home page display + * + */ +static void ui_home_init(void) { char name[32]; unsigned int serial = U4BE(G_gpg_vstate.kslot->serial, 0); @@ -114,14 +152,60 @@ void ui_init(void) { serial, G_gpg_vstate.slot + 1); - nbgl_useCaseHomeExt(APPNAME, - &C_gpg_64px, - G_gpg_vstate.menu, - true, - "Select Slot", - ui_menu_slot_action, - ui_menu_settings, - app_quit); + static nbgl_contentInfoList_t infosList = {0}; + + static const char* const infoTypes[] = {"Version", "Specifications", "Developer"}; + static const char* const infoContents[] = {APPVERSION, XSTR(SPEC_VERSION), "(c) 2024 Ledger"}; + + infosList.nbInfos = ARRAYLEN(infoTypes); + infosList.infoTypes = (const char**) infoTypes; + infosList.infoContents = (const char**) infoContents; + + static nbgl_content_t contents = {0}; + static nbgl_genericContents_t settingContents = {0}; + + static const char* const barTexts[] = {"Key Template", + "Seed mode", + "Pin mode", + "UIF mode", + "Reset"}; + static const uint8_t barTokens[] = {TOKEN_SETTINGS_TEMPLATE, + TOKEN_SETTINGS_SEED, + TOKEN_SETTINGS_PIN, + TOKEN_SETTINGS_UIF, + TOKEN_SETTINGS_RESET}; + contents.type = BARS_LIST; + contents.content.barsList.barTexts = barTexts; + contents.content.barsList.tokens = barTokens; + contents.content.barsList.nbBars = ARRAYLEN(barTexts); + contents.content.barsList.tuneId = TUNE_TAP_CASUAL; + contents.contentActionCallback = controlsCallback; + + settingContents.callbackCallNeeded = false; + settingContents.contentsList = &contents; + settingContents.nbContents = 1; + + static nbgl_homeAction_t actionContent = {0}; + actionContent.text = "Select Slot"; + actionContent.callback = ui_menu_slot_action; + + nbgl_useCaseHomeAndSettings(APPNAME, + &C_gpg_64px, + G_gpg_vstate.menu, + setting_initPage, + &settingContents, + &infosList, + &actionContent, + app_quit); +} + +/** + * home page init + * + */ +void ui_init(void) { + setting_initPage = INIT_HOME_PAGE; + ui_home_init(); } // ----------------------------------------------------------- @@ -239,6 +323,16 @@ static const char* const keyTypeTexts[] = {LABEL_RSA2048, LABEL_SECP256R1, LABEL_Ed25519}; +#ifdef NO_DECRYPT_cv25519 +static const char* const keyTypeDecTexts[] = {LABEL_RSA2048, + LABEL_RSA3072, +#ifdef WITH_SUPPORT_RSA4096 + LABEL_RSA4096, +#endif + LABEL_SECP256K1, + LABEL_SECP256R1}; +#endif + /** * Determine the selected key type from its attributes * @@ -429,7 +523,7 @@ static void template_cb(int token, uint8_t index) { switch (token) { case TOKEN_TEMPLATE_BACK: - ui_menu_settings(); + ui_home_init(); break; case TOKEN_TEMPLATE_SIG: case TOKEN_TEMPLATE_DEC: @@ -439,8 +533,16 @@ static void template_cb(int token, uint8_t index) { TOKEN_TYPE_BACK, template_key_cb); - choices.names = (const char* const*) keyTypeTexts; - choices.nbChoices = ARRAYLEN(keyTypeTexts); +#ifdef NO_DECRYPT_cv25519 + if (token == TOKEN_TEMPLATE_DEC) { + choices.names = (const char* const*) keyTypeDecTexts; + choices.nbChoices = ARRAYLEN(keyTypeDecTexts); + } else +#endif + { + choices.names = (const char* const*) keyTypeTexts; + choices.nbChoices = ARRAYLEN(keyTypeTexts); + } choices.initChoice = _getKeyType(token) - FIRST_USER_TOKEN; choices.token = token; nbgl_layoutAddRadioChoice(layoutCtx, &choices); @@ -451,7 +553,7 @@ static void template_cb(int token, uint8_t index) { } /** - * Template Navigation callback + * Template Settings menu * */ static void ui_settings_template(void) { @@ -489,7 +591,7 @@ static void ui_settings_template(void) { break; } bar.text = PIC(keyNameTexts[i]); - bar.iconRight = &C_Next32px; + bar.iconRight = &RIGHT_ARROW_ICON; bar.token = TOKEN_TEMPLATE_SIG + i; bar.centered = false; bar.tuneId = TUNE_TAP_CASUAL; @@ -533,7 +635,7 @@ void seed_confirm_cb(bool confirm) { static void seed_cb(int token, uint8_t index) { switch (token) { case TOKEN_SEED_BACK: - ui_menu_settings(); + ui_home_init(); break; case TOKEN_SEED: if (index == 0) { @@ -552,7 +654,7 @@ static void seed_cb(int token, uint8_t index) { } /** - * Seed Navigation callback + * Seed Settings menu * */ static void ui_settings_seed(void) { @@ -604,7 +706,7 @@ static void pin_cb(int token, uint8_t index) { const char* err = NULL; switch (token) { case TOKEN_PIN_BACK: - ui_menu_settings(); + ui_home_init(); break; case TOKEN_PIN_SET: if (G_gpg_vstate.pinmode == index) { @@ -657,7 +759,7 @@ static void pin_cb(int token, uint8_t index) { } /** - * Pin Navigation callback + * Pin Settings menu * */ static void ui_settings_pin(void) { @@ -721,7 +823,7 @@ static void uif_cb(int token, uint8_t index) { unsigned char* uif = NULL; switch (token) { case TOKEN_UIF_BACK: - ui_menu_settings(); + ui_home_init(); break; case TOKEN_UIF_SIG: uif = &G_gpg_vstate.kslot->sig.UIF[0]; @@ -737,14 +839,14 @@ static void uif_cb(int token, uint8_t index) { return; } if (uif[0] == 2) { - ui_info(UIF_LOCKED, EMPTY, ui_menu_settings, false); + ui_info(UIF_LOCKED, EMPTY, ui_home_init, false); } else if (uif[0] != index) { nvm_write(&uif[0], &index, 1); } } /** - * UIF Navigation callback + * UIF Settings menu * */ static void ui_settings_uif(void) { @@ -802,161 +904,53 @@ static void ui_settings_uif(void) { /* -------------------------------- RESET UX --------------------------------- */ -enum { - TOKEN_RESET = FIRST_USER_TOKEN, -}; +enum { TOKEN_RESET = FIRST_USER_TOKEN, TOKEN_RESET_BACK }; -/** - * Reset Navigation callback - * - * @param[in] page selected page to display - * @param[in] content describe the widgets to display on the page - * - */ -static bool reset_nav_cb(uint8_t page, nbgl_pageContent_t* content) { - UNUSED(page); - explicit_bzero(content, sizeof(nbgl_pageContent_t)); - content->type = INFO_LONG_PRESS; - content->infoLongPress.text = - "Reset the app to factory default?\nThis will delete ALL the keys!!!"; - content->infoLongPress.icon = NULL; - content->infoLongPress.longPressText = "Yes"; - content->infoLongPress.longPressToken = TOKEN_RESET; - content->infoLongPress.tuneId = TUNE_TAP_CASUAL; - return true; +static void reset_cb(int token, uint8_t index) { + setting_initPage = 0; + switch (token) { + case TOKEN_RESET_BACK: + ui_home_init(); + break; + case TOKEN_RESET: + switch (index) { + case 0: + app_reset(); + ui_info("App Reset", "Done", ui_init, true); + break; + case 1: + ui_home_init(); + break; + } + break; + } } /** - * Reset Action callback - * - * @param[in] token button Id pressed - * @param[in] index widget index on the page + * Reset Settings menu * */ -static void reset_ctrl_cb(int token, uint8_t index) { - UNUSED(index); - - if (token != TOKEN_RESET) { - return; - } - - app_reset(); -} - -/* ------------------------------- SETTINGS UX ------------------------------- */ - -enum { - TOKEN_SETTINGS_TEMPLATE = FIRST_USER_TOKEN, - TOKEN_SETTINGS_SEED, - TOKEN_SETTINGS_PIN, - TOKEN_SETTINGS_UIF, - TOKEN_SETTINGS_RESET, -}; +static void ui_reset(void) { + nbgl_contentCenteredInfo_t centeredInfo = {0}; + nbgl_layoutChoiceButtons_t buttonInfo = {0}; -enum { - SETTINGS_PAGE_PARAMS, - SETTINGS_PAGE_INFO, - SETTINGS_PAGE_NB, -}; + ui_setting_header("Reset to Default", TOKEN_RESET_BACK, reset_cb); -#ifdef HAVE_PRINTF -#define VERSION_STR "[DBG] App " XSTR(APPVERSION) -#else -#define VERSION_STR "App " XSTR(APPVERSION) -#endif + centeredInfo.onTop = true; + centeredInfo.text1 = "This will reset the app to factory default,\nand delete ALL the keys!!!"; + centeredInfo.text2 = "Are you sure you want to continue?"; + centeredInfo.style = LARGE_CASE_BOLD_INFO; -/** - * Settings Navigation callback - * - * @param[in] page selected page to display - * @param[in] content describe the widgets to display on the page - * - */ -static bool settings_nav_cb(uint8_t page, nbgl_pageContent_t* content) { - bool ret = false; - - static const char* const infoTypes[] = {"Name", "Developer", "Specifications", "Version"}; - static const char* const infoContents[] = {"OpenPGP Card", - "(c) Ledger SAS", - XSTR(SPEC_VERSION), - VERSION_STR}; - static const char* const barTexts[] = {"Key Template", - "Seed mode", - "Pin mode", - "UIF mode", - "Reset"}; - static const uint8_t barTokens[] = {TOKEN_SETTINGS_TEMPLATE, - TOKEN_SETTINGS_SEED, - TOKEN_SETTINGS_PIN, - TOKEN_SETTINGS_UIF, - TOKEN_SETTINGS_RESET}; - explicit_bzero(content, sizeof(nbgl_pageContent_t)); - switch (page) { - case SETTINGS_PAGE_INFO: - content->type = INFOS_LIST; - content->infosList.nbInfos = ARRAYLEN(infoTypes); - content->infosList.infoTypes = infoTypes; - content->infosList.infoContents = infoContents; - ret = true; - break; - case SETTINGS_PAGE_PARAMS: - content->type = BARS_LIST; - content->barsList.barTexts = barTexts; - content->barsList.tokens = barTokens; - content->barsList.nbBars = ARRAYLEN(barTokens); - content->barsList.tuneId = TUNE_TAP_CASUAL; - ret = true; - break; - } - return ret; -} + nbgl_layoutAddCenteredInfo(layoutCtx, ¢eredInfo); -/** - * Settings Action callback - * - * @param[in] token button Id pressed - * @param[in] index widget index on the page - * - */ -static void settings_ctrl_cb(int token, uint8_t index) { - UNUSED(index); - switch (token) { - case TOKEN_SETTINGS_TEMPLATE: - ui_settings_template(); - break; - case TOKEN_SETTINGS_SEED: - ui_settings_seed(); - break; - case TOKEN_SETTINGS_PIN: - ui_settings_pin(); - break; - case TOKEN_SETTINGS_UIF: - ui_settings_uif(); - break; - case TOKEN_SETTINGS_RESET: - nbgl_useCaseSettings("Reset to Default", - 0, - 1, - true, - ui_menu_settings, - reset_nav_cb, - reset_ctrl_cb); - break; - } -} + buttonInfo.topText = "Reset"; + buttonInfo.bottomText = "Cancel"; + buttonInfo.token = TOKEN_RESET; + buttonInfo.style = BOTH_ROUNDED_STYLE; + buttonInfo.tuneId = TUNE_TAP_CASUAL; + nbgl_layoutAddChoiceButtons(layoutCtx, &buttonInfo); -/** - * Settings menu definition - * - */ -static void ui_menu_settings() { - nbgl_useCaseSettings(APPNAME, - SETTINGS_PAGE_PARAMS, - SETTINGS_PAGE_NB, - false, - ui_init, - settings_nav_cb, - settings_ctrl_cb); + nbgl_layoutDraw(layoutCtx); } /* ------------------------------ PIN CONFIRM UX ----------------------------- */ @@ -1156,14 +1150,14 @@ void ui_menu_pinentry_display(unsigned int step) { minLen = (G_gpg_vstate.io_p2 == PIN_ID_PW3) ? GPG_MIN_PW3_LENGTH : GPG_MIN_PW1_LENGTH; // Draw the keypad - nbgl_useCaseKeypad(G_gpg_vstate.menu, - minLen, - GPG_MAX_PW_LENGTH, - TOKEN_PIN_ENTRY_BACK, - false, - TUNE_TAP_CASUAL, - pinentry_validate_cb, - pinentry_cb); + nbgl_useCaseKeypadPIN(G_gpg_vstate.menu, + minLen, + GPG_MAX_PW_LENGTH, + TOKEN_PIN_ENTRY_BACK, + false, + TUNE_TAP_CASUAL, + pinentry_validate_cb, + pinentry_cb); } /** @@ -1246,4 +1240,4 @@ void ui_menu_uifconfirm_display(unsigned int value) { nbgl_useCaseChoice(NULL, "Confirm operation", G_gpg_vstate.menu, "Yes", "No", uif_confirm_cb); } -#endif // defined(HAVE_NBGL) && defined(TARGET_STAX) +#endif // defined(HAVE_NBGL) && (defined(TARGET_STAX) || defined(TARGET_FLEX)) diff --git a/tests/snapshots/flex/test_menu_settings/00000.png b/tests/snapshots/flex/test_menu_settings/00000.png new file mode 100644 index 0000000..be43f99 Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00000.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00001.png b/tests/snapshots/flex/test_menu_settings/00001.png new file mode 100644 index 0000000..20671d5 Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00001.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00002.png b/tests/snapshots/flex/test_menu_settings/00002.png new file mode 100644 index 0000000..8df8b4d Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00002.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00003.png b/tests/snapshots/flex/test_menu_settings/00003.png new file mode 100644 index 0000000..a612494 Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00003.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00004.png b/tests/snapshots/flex/test_menu_settings/00004.png new file mode 100644 index 0000000..be43f99 Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00004.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00005.png b/tests/snapshots/flex/test_menu_settings/00005.png new file mode 100644 index 0000000..a7999d0 Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00005.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00006.png b/tests/snapshots/flex/test_menu_settings/00006.png new file mode 100644 index 0000000..be43f99 Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00006.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00007.png b/tests/snapshots/flex/test_menu_settings/00007.png new file mode 100644 index 0000000..4f88e70 Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00007.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00008.png b/tests/snapshots/flex/test_menu_settings/00008.png new file mode 100644 index 0000000..5d883f5 Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00008.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00009.png b/tests/snapshots/flex/test_menu_settings/00009.png new file mode 100644 index 0000000..3999c2e Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00009.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00010.png b/tests/snapshots/flex/test_menu_settings/00010.png new file mode 100644 index 0000000..be43f99 Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00010.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00011.png b/tests/snapshots/flex/test_menu_settings/00011.png new file mode 100644 index 0000000..efdba7a Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00011.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00012.png b/tests/snapshots/flex/test_menu_settings/00012.png new file mode 100644 index 0000000..693a82e Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00012.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00013.png b/tests/snapshots/flex/test_menu_settings/00013.png new file mode 100644 index 0000000..be43f99 Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00013.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00014.png b/tests/snapshots/flex/test_menu_settings/00014.png new file mode 100644 index 0000000..a73d77b Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00014.png differ diff --git a/tests/snapshots/flex/test_menu_settings/00015.png b/tests/snapshots/flex/test_menu_settings/00015.png new file mode 100644 index 0000000..9e1032c Binary files /dev/null and b/tests/snapshots/flex/test_menu_settings/00015.png differ diff --git a/tests/snapshots/flex/test_menu_slot/00000.png b/tests/snapshots/flex/test_menu_slot/00000.png new file mode 100644 index 0000000..8a464c4 Binary files /dev/null and b/tests/snapshots/flex/test_menu_slot/00000.png differ diff --git a/tests/snapshots/flex/test_menu_slot/00001.png b/tests/snapshots/flex/test_menu_slot/00001.png new file mode 100644 index 0000000..b6d3170 Binary files /dev/null and b/tests/snapshots/flex/test_menu_slot/00001.png differ diff --git a/tests/snapshots/flex/test_verify_confirm_accepted/00000.png b/tests/snapshots/flex/test_verify_confirm_accepted/00000.png new file mode 100644 index 0000000..2741b87 Binary files /dev/null and b/tests/snapshots/flex/test_verify_confirm_accepted/00000.png differ diff --git a/tests/snapshots/flex/test_verify_confirm_refused/00000.png b/tests/snapshots/flex/test_verify_confirm_refused/00000.png new file mode 100644 index 0000000..2741b87 Binary files /dev/null and b/tests/snapshots/flex/test_verify_confirm_refused/00000.png differ diff --git a/tests/snapshots/nanos/test_menu_settings/00006.png b/tests/snapshots/nanos/test_menu_settings/00006.png index f434eb1..1a91597 100644 Binary files a/tests/snapshots/nanos/test_menu_settings/00006.png and b/tests/snapshots/nanos/test_menu_settings/00006.png differ diff --git a/tests/snapshots/nanos/test_menu_settings/00007.png b/tests/snapshots/nanos/test_menu_settings/00007.png index 280b683..f434eb1 100644 Binary files a/tests/snapshots/nanos/test_menu_settings/00007.png and b/tests/snapshots/nanos/test_menu_settings/00007.png differ diff --git a/tests/snapshots/nanos/test_menu_settings/00008.png b/tests/snapshots/nanos/test_menu_settings/00008.png index 41bbb72..280b683 100644 Binary files a/tests/snapshots/nanos/test_menu_settings/00008.png and b/tests/snapshots/nanos/test_menu_settings/00008.png differ diff --git a/tests/snapshots/nanos/test_menu_settings/00009.png b/tests/snapshots/nanos/test_menu_settings/00009.png index 81ce431..a7767a8 100644 Binary files a/tests/snapshots/nanos/test_menu_settings/00009.png and b/tests/snapshots/nanos/test_menu_settings/00009.png differ diff --git a/tests/snapshots/nanos/test_menu_settings/00013.png b/tests/snapshots/nanos/test_menu_settings/00013.png index 81ce431..a7767a8 100644 Binary files a/tests/snapshots/nanos/test_menu_settings/00013.png and b/tests/snapshots/nanos/test_menu_settings/00013.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00004.png b/tests/snapshots/nanosp/test_menu_settings/00004.png index 4f44ce5..621043a 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00004.png and b/tests/snapshots/nanosp/test_menu_settings/00004.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00005.png b/tests/snapshots/nanosp/test_menu_settings/00005.png index fb049ec..f0517b5 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00005.png and b/tests/snapshots/nanosp/test_menu_settings/00005.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00006.png b/tests/snapshots/nanosp/test_menu_settings/00006.png index 99fc174..fb049ec 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00006.png and b/tests/snapshots/nanosp/test_menu_settings/00006.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00007.png b/tests/snapshots/nanosp/test_menu_settings/00007.png index 3ad71f8..99fc174 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00007.png and b/tests/snapshots/nanosp/test_menu_settings/00007.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00008.png b/tests/snapshots/nanosp/test_menu_settings/00008.png index e678a83..3ad71f8 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00008.png and b/tests/snapshots/nanosp/test_menu_settings/00008.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00009.png b/tests/snapshots/nanosp/test_menu_settings/00009.png index 03a2ed8..e678a83 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00009.png and b/tests/snapshots/nanosp/test_menu_settings/00009.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00010.png b/tests/snapshots/nanosp/test_menu_settings/00010.png index ae682df..03a2ed8 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00010.png and b/tests/snapshots/nanosp/test_menu_settings/00010.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00011.png b/tests/snapshots/nanosp/test_menu_settings/00011.png index 160a0ea..ae682df 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00011.png and b/tests/snapshots/nanosp/test_menu_settings/00011.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00012.png b/tests/snapshots/nanosp/test_menu_settings/00012.png index ae682df..160a0ea 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00012.png and b/tests/snapshots/nanosp/test_menu_settings/00012.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00013.png b/tests/snapshots/nanosp/test_menu_settings/00013.png index 160a0ea..f0517b5 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00013.png and b/tests/snapshots/nanosp/test_menu_settings/00013.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00014.png b/tests/snapshots/nanosp/test_menu_settings/00014.png index 61861f2..ae682df 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00014.png and b/tests/snapshots/nanosp/test_menu_settings/00014.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00015.png b/tests/snapshots/nanosp/test_menu_settings/00015.png index 993d953..160a0ea 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00015.png and b/tests/snapshots/nanosp/test_menu_settings/00015.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00016.png b/tests/snapshots/nanosp/test_menu_settings/00016.png index f14db00..61861f2 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00016.png and b/tests/snapshots/nanosp/test_menu_settings/00016.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00017.png b/tests/snapshots/nanosp/test_menu_settings/00017.png index 39f8d72..993d953 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00017.png and b/tests/snapshots/nanosp/test_menu_settings/00017.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00018.png b/tests/snapshots/nanosp/test_menu_settings/00018.png index 61861f2..f14db00 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00018.png and b/tests/snapshots/nanosp/test_menu_settings/00018.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00019.png b/tests/snapshots/nanosp/test_menu_settings/00019.png index f14db00..39f8d72 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00019.png and b/tests/snapshots/nanosp/test_menu_settings/00019.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00020.png b/tests/snapshots/nanosp/test_menu_settings/00020.png index f853849..61861f2 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00020.png and b/tests/snapshots/nanosp/test_menu_settings/00020.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00021.png b/tests/snapshots/nanosp/test_menu_settings/00021.png index 21c1ee6..f14db00 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00021.png and b/tests/snapshots/nanosp/test_menu_settings/00021.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00022.png b/tests/snapshots/nanosp/test_menu_settings/00022.png index 6d667a9..f853849 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00022.png and b/tests/snapshots/nanosp/test_menu_settings/00022.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00023.png b/tests/snapshots/nanosp/test_menu_settings/00023.png index 2d4b009..21c1ee6 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00023.png and b/tests/snapshots/nanosp/test_menu_settings/00023.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00024.png b/tests/snapshots/nanosp/test_menu_settings/00024.png index 181fcd2..6d667a9 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00024.png and b/tests/snapshots/nanosp/test_menu_settings/00024.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00025.png b/tests/snapshots/nanosp/test_menu_settings/00025.png index 31947f4..2d4b009 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00025.png and b/tests/snapshots/nanosp/test_menu_settings/00025.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00026.png b/tests/snapshots/nanosp/test_menu_settings/00026.png index 6dfd92d..181fcd2 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00026.png and b/tests/snapshots/nanosp/test_menu_settings/00026.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00027.png b/tests/snapshots/nanosp/test_menu_settings/00027.png index 42a79ad..31947f4 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00027.png and b/tests/snapshots/nanosp/test_menu_settings/00027.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00028.png b/tests/snapshots/nanosp/test_menu_settings/00028.png index 181fcd2..6dfd92d 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00028.png and b/tests/snapshots/nanosp/test_menu_settings/00028.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00029.png b/tests/snapshots/nanosp/test_menu_settings/00029.png index 31947f4..42a79ad 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00029.png and b/tests/snapshots/nanosp/test_menu_settings/00029.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00030.png b/tests/snapshots/nanosp/test_menu_settings/00030.png index 61861f2..181fcd2 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00030.png and b/tests/snapshots/nanosp/test_menu_settings/00030.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00031.png b/tests/snapshots/nanosp/test_menu_settings/00031.png index f853849..31947f4 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00031.png and b/tests/snapshots/nanosp/test_menu_settings/00031.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00032.png b/tests/snapshots/nanosp/test_menu_settings/00032.png index 09f86e3..61861f2 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00032.png and b/tests/snapshots/nanosp/test_menu_settings/00032.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00033.png b/tests/snapshots/nanosp/test_menu_settings/00033.png index 82790bc..f853849 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00033.png and b/tests/snapshots/nanosp/test_menu_settings/00033.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00034.png b/tests/snapshots/nanosp/test_menu_settings/00034.png index e525706..09f86e3 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00034.png and b/tests/snapshots/nanosp/test_menu_settings/00034.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00035.png b/tests/snapshots/nanosp/test_menu_settings/00035.png index 1418d03..82790bc 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00035.png and b/tests/snapshots/nanosp/test_menu_settings/00035.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00036.png b/tests/snapshots/nanosp/test_menu_settings/00036.png index ecec8c2..e525706 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00036.png and b/tests/snapshots/nanosp/test_menu_settings/00036.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00037.png b/tests/snapshots/nanosp/test_menu_settings/00037.png index 61861f2..1418d03 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00037.png and b/tests/snapshots/nanosp/test_menu_settings/00037.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00038.png b/tests/snapshots/nanosp/test_menu_settings/00038.png index 09f86e3..ecec8c2 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00038.png and b/tests/snapshots/nanosp/test_menu_settings/00038.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00039.png b/tests/snapshots/nanosp/test_menu_settings/00039.png index 15222f2..61861f2 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00039.png and b/tests/snapshots/nanosp/test_menu_settings/00039.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00040.png b/tests/snapshots/nanosp/test_menu_settings/00040.png index ad5e1c1..09f86e3 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00040.png and b/tests/snapshots/nanosp/test_menu_settings/00040.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00041.png b/tests/snapshots/nanosp/test_menu_settings/00041.png index d993684..15222f2 100644 Binary files a/tests/snapshots/nanosp/test_menu_settings/00041.png and b/tests/snapshots/nanosp/test_menu_settings/00041.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00042.png b/tests/snapshots/nanosp/test_menu_settings/00042.png new file mode 100644 index 0000000..ad5e1c1 Binary files /dev/null and b/tests/snapshots/nanosp/test_menu_settings/00042.png differ diff --git a/tests/snapshots/nanosp/test_menu_settings/00043.png b/tests/snapshots/nanosp/test_menu_settings/00043.png new file mode 100644 index 0000000..d993684 Binary files /dev/null and b/tests/snapshots/nanosp/test_menu_settings/00043.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00004.png b/tests/snapshots/nanox/test_menu_settings/00004.png index 4f44ce5..621043a 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00004.png and b/tests/snapshots/nanox/test_menu_settings/00004.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00005.png b/tests/snapshots/nanox/test_menu_settings/00005.png index fb049ec..f0517b5 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00005.png and b/tests/snapshots/nanox/test_menu_settings/00005.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00006.png b/tests/snapshots/nanox/test_menu_settings/00006.png index 99fc174..fb049ec 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00006.png and b/tests/snapshots/nanox/test_menu_settings/00006.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00007.png b/tests/snapshots/nanox/test_menu_settings/00007.png index 3ad71f8..99fc174 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00007.png and b/tests/snapshots/nanox/test_menu_settings/00007.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00008.png b/tests/snapshots/nanox/test_menu_settings/00008.png index e678a83..3ad71f8 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00008.png and b/tests/snapshots/nanox/test_menu_settings/00008.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00009.png b/tests/snapshots/nanox/test_menu_settings/00009.png index 03a2ed8..e678a83 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00009.png and b/tests/snapshots/nanox/test_menu_settings/00009.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00010.png b/tests/snapshots/nanox/test_menu_settings/00010.png index ae682df..03a2ed8 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00010.png and b/tests/snapshots/nanox/test_menu_settings/00010.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00011.png b/tests/snapshots/nanox/test_menu_settings/00011.png index 160a0ea..ae682df 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00011.png and b/tests/snapshots/nanox/test_menu_settings/00011.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00012.png b/tests/snapshots/nanox/test_menu_settings/00012.png index ae682df..160a0ea 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00012.png and b/tests/snapshots/nanox/test_menu_settings/00012.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00013.png b/tests/snapshots/nanox/test_menu_settings/00013.png index 160a0ea..f0517b5 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00013.png and b/tests/snapshots/nanox/test_menu_settings/00013.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00014.png b/tests/snapshots/nanox/test_menu_settings/00014.png index 61861f2..ae682df 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00014.png and b/tests/snapshots/nanox/test_menu_settings/00014.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00015.png b/tests/snapshots/nanox/test_menu_settings/00015.png index 993d953..160a0ea 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00015.png and b/tests/snapshots/nanox/test_menu_settings/00015.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00016.png b/tests/snapshots/nanox/test_menu_settings/00016.png index f14db00..61861f2 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00016.png and b/tests/snapshots/nanox/test_menu_settings/00016.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00017.png b/tests/snapshots/nanox/test_menu_settings/00017.png index 39f8d72..993d953 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00017.png and b/tests/snapshots/nanox/test_menu_settings/00017.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00018.png b/tests/snapshots/nanox/test_menu_settings/00018.png index 61861f2..f14db00 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00018.png and b/tests/snapshots/nanox/test_menu_settings/00018.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00019.png b/tests/snapshots/nanox/test_menu_settings/00019.png index f14db00..39f8d72 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00019.png and b/tests/snapshots/nanox/test_menu_settings/00019.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00020.png b/tests/snapshots/nanox/test_menu_settings/00020.png index f853849..61861f2 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00020.png and b/tests/snapshots/nanox/test_menu_settings/00020.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00021.png b/tests/snapshots/nanox/test_menu_settings/00021.png index 21c1ee6..f14db00 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00021.png and b/tests/snapshots/nanox/test_menu_settings/00021.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00022.png b/tests/snapshots/nanox/test_menu_settings/00022.png index 6d667a9..f853849 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00022.png and b/tests/snapshots/nanox/test_menu_settings/00022.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00023.png b/tests/snapshots/nanox/test_menu_settings/00023.png index 2d4b009..21c1ee6 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00023.png and b/tests/snapshots/nanox/test_menu_settings/00023.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00024.png b/tests/snapshots/nanox/test_menu_settings/00024.png index 181fcd2..6d667a9 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00024.png and b/tests/snapshots/nanox/test_menu_settings/00024.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00025.png b/tests/snapshots/nanox/test_menu_settings/00025.png index 31947f4..2d4b009 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00025.png and b/tests/snapshots/nanox/test_menu_settings/00025.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00026.png b/tests/snapshots/nanox/test_menu_settings/00026.png index 6dfd92d..181fcd2 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00026.png and b/tests/snapshots/nanox/test_menu_settings/00026.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00027.png b/tests/snapshots/nanox/test_menu_settings/00027.png index 42a79ad..31947f4 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00027.png and b/tests/snapshots/nanox/test_menu_settings/00027.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00028.png b/tests/snapshots/nanox/test_menu_settings/00028.png index 181fcd2..6dfd92d 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00028.png and b/tests/snapshots/nanox/test_menu_settings/00028.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00029.png b/tests/snapshots/nanox/test_menu_settings/00029.png index 31947f4..42a79ad 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00029.png and b/tests/snapshots/nanox/test_menu_settings/00029.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00030.png b/tests/snapshots/nanox/test_menu_settings/00030.png index 61861f2..181fcd2 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00030.png and b/tests/snapshots/nanox/test_menu_settings/00030.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00031.png b/tests/snapshots/nanox/test_menu_settings/00031.png index f853849..31947f4 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00031.png and b/tests/snapshots/nanox/test_menu_settings/00031.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00032.png b/tests/snapshots/nanox/test_menu_settings/00032.png index 09f86e3..61861f2 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00032.png and b/tests/snapshots/nanox/test_menu_settings/00032.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00033.png b/tests/snapshots/nanox/test_menu_settings/00033.png index 82790bc..f853849 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00033.png and b/tests/snapshots/nanox/test_menu_settings/00033.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00034.png b/tests/snapshots/nanox/test_menu_settings/00034.png index e525706..09f86e3 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00034.png and b/tests/snapshots/nanox/test_menu_settings/00034.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00035.png b/tests/snapshots/nanox/test_menu_settings/00035.png index 1418d03..82790bc 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00035.png and b/tests/snapshots/nanox/test_menu_settings/00035.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00036.png b/tests/snapshots/nanox/test_menu_settings/00036.png index ecec8c2..e525706 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00036.png and b/tests/snapshots/nanox/test_menu_settings/00036.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00037.png b/tests/snapshots/nanox/test_menu_settings/00037.png index 61861f2..1418d03 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00037.png and b/tests/snapshots/nanox/test_menu_settings/00037.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00038.png b/tests/snapshots/nanox/test_menu_settings/00038.png index 09f86e3..ecec8c2 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00038.png and b/tests/snapshots/nanox/test_menu_settings/00038.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00039.png b/tests/snapshots/nanox/test_menu_settings/00039.png index 15222f2..61861f2 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00039.png and b/tests/snapshots/nanox/test_menu_settings/00039.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00040.png b/tests/snapshots/nanox/test_menu_settings/00040.png index ad5e1c1..09f86e3 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00040.png and b/tests/snapshots/nanox/test_menu_settings/00040.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00041.png b/tests/snapshots/nanox/test_menu_settings/00041.png index d993684..15222f2 100644 Binary files a/tests/snapshots/nanox/test_menu_settings/00041.png and b/tests/snapshots/nanox/test_menu_settings/00041.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00042.png b/tests/snapshots/nanox/test_menu_settings/00042.png new file mode 100644 index 0000000..ad5e1c1 Binary files /dev/null and b/tests/snapshots/nanox/test_menu_settings/00042.png differ diff --git a/tests/snapshots/nanox/test_menu_settings/00043.png b/tests/snapshots/nanox/test_menu_settings/00043.png new file mode 100644 index 0000000..d993684 Binary files /dev/null and b/tests/snapshots/nanox/test_menu_settings/00043.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00000.png b/tests/snapshots/stax/test_menu_settings/00000.png index 9a586a4..003a37e 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00000.png and b/tests/snapshots/stax/test_menu_settings/00000.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00001.png b/tests/snapshots/stax/test_menu_settings/00001.png index ea5bea4..73342c5 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00001.png and b/tests/snapshots/stax/test_menu_settings/00001.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00002.png b/tests/snapshots/stax/test_menu_settings/00002.png index ac4f499..8feb57a 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00002.png and b/tests/snapshots/stax/test_menu_settings/00002.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00003.png b/tests/snapshots/stax/test_menu_settings/00003.png index 083b413..6b7d311 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00003.png and b/tests/snapshots/stax/test_menu_settings/00003.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00004.png b/tests/snapshots/stax/test_menu_settings/00004.png index 9a586a4..003a37e 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00004.png and b/tests/snapshots/stax/test_menu_settings/00004.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00005.png b/tests/snapshots/stax/test_menu_settings/00005.png index 4641f1e..6520168 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00005.png and b/tests/snapshots/stax/test_menu_settings/00005.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00006.png b/tests/snapshots/stax/test_menu_settings/00006.png index 9a586a4..003a37e 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00006.png and b/tests/snapshots/stax/test_menu_settings/00006.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00007.png b/tests/snapshots/stax/test_menu_settings/00007.png index 5d4e90c..32a086a 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00007.png and b/tests/snapshots/stax/test_menu_settings/00007.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00008.png b/tests/snapshots/stax/test_menu_settings/00008.png index 770b9cc..7d2bbc8 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00008.png and b/tests/snapshots/stax/test_menu_settings/00008.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00009.png b/tests/snapshots/stax/test_menu_settings/00009.png index 673d6b6..06cdee3 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00009.png and b/tests/snapshots/stax/test_menu_settings/00009.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00010.png b/tests/snapshots/stax/test_menu_settings/00010.png index 9a586a4..003a37e 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00010.png and b/tests/snapshots/stax/test_menu_settings/00010.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00011.png b/tests/snapshots/stax/test_menu_settings/00011.png index ed5921a..4b39201 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00011.png and b/tests/snapshots/stax/test_menu_settings/00011.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00012.png b/tests/snapshots/stax/test_menu_settings/00012.png index 213818d..2f0cf16 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00012.png and b/tests/snapshots/stax/test_menu_settings/00012.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00013.png b/tests/snapshots/stax/test_menu_settings/00013.png index 9a586a4..003a37e 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00013.png and b/tests/snapshots/stax/test_menu_settings/00013.png differ diff --git a/tests/snapshots/stax/test_menu_settings/00014.png b/tests/snapshots/stax/test_menu_settings/00014.png index 4941e0d..018c087 100644 Binary files a/tests/snapshots/stax/test_menu_settings/00014.png and b/tests/snapshots/stax/test_menu_settings/00014.png differ diff --git a/tests/snapshots/stax/test_menu_slot/00000.png b/tests/snapshots/stax/test_menu_slot/00000.png index 7cb169a..a0509ad 100644 Binary files a/tests/snapshots/stax/test_menu_slot/00000.png and b/tests/snapshots/stax/test_menu_slot/00000.png differ diff --git a/tests/snapshots/stax/test_menu_slot/00001.png b/tests/snapshots/stax/test_menu_slot/00001.png index 85c4b77..a9bb273 100644 Binary files a/tests/snapshots/stax/test_menu_slot/00001.png and b/tests/snapshots/stax/test_menu_slot/00001.png differ diff --git a/tests/snapshots/stax/test_verify_confirm_accepted/00000.png b/tests/snapshots/stax/test_verify_confirm_accepted/00000.png index 38dd8e0..06dcb0a 100644 Binary files a/tests/snapshots/stax/test_verify_confirm_accepted/00000.png and b/tests/snapshots/stax/test_verify_confirm_accepted/00000.png differ diff --git a/tests/snapshots/stax/test_verify_confirm_refused/00000.png b/tests/snapshots/stax/test_verify_confirm_refused/00000.png index 38dd8e0..06dcb0a 100644 Binary files a/tests/snapshots/stax/test_verify_confirm_refused/00000.png and b/tests/snapshots/stax/test_verify_confirm_refused/00000.png differ diff --git a/tests/test_cipher.py b/tests/test_cipher.py index f81088b..70ab418 100644 --- a/tests/test_cipher.py +++ b/tests/test_cipher.py @@ -7,6 +7,8 @@ from Crypto.Random import get_random_bytes from Crypto.Cipher import PKCS1_v1_5 +from ragger.backend import BackendInterface + from application_client.command_sender import CommandSender from application_client.app_def import Errors, DataObject, PassWord @@ -14,7 +16,7 @@ # In this test we check the symmetric key encryption -def test_AES(backend): +def test_AES(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -42,7 +44,7 @@ def test_AES(backend): # In this test we check the symmetric key encryption -def test_Asym(backend): +def test_Asym(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -68,7 +70,7 @@ def test_Asym(backend): # In this test we check the symmetric key encryption with MSE -def test_MSE(backend): +def test_MSE(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) diff --git a/tests/test_menus.py b/tests/test_menus.py index 7b29162..5740360 100644 --- a/tests/test_menus.py +++ b/tests/test_menus.py @@ -1,5 +1,9 @@ +from typing import Sequence import pytest -from ragger.navigator import NavInsID, NavIns +from ragger.backend import BackendInterface +from ragger.firmware import Firmware +from ragger.navigator import Navigator, NavInsID, NavIns +from ragger.navigator.navigator import InstructionType from application_client.command_sender import CommandSender from application_client.app_def import PassWord @@ -11,7 +15,7 @@ # In this test we check the behavior of the Slot menu # The Navigations go and check: # - Select slot / Slot 2 / (next page) / Set default -def test_menu_slot(firmware, backend, navigator, test_name): +def test_menu_slot(firmware: Firmware, backend: BackendInterface, navigator: Navigator, test_name: str) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -24,7 +28,8 @@ def test_menu_slot(firmware, backend, navigator, test_name): pytest.skip("single slot configuration") # Navigate in the main menu - if firmware.device.startswith("nano"): + instructions: Sequence[InstructionType] + if firmware.is_nano: initial_instructions = [ NavInsID.RIGHT_CLICK, NavInsID.BOTH_CLICK, # Select slot @@ -40,6 +45,7 @@ def test_menu_slot(firmware, backend, navigator, test_name): NavInsID.RIGHT_CLICK, NavInsID.BOTH_CLICK, # (Back) ] + else: initial_instructions = [ NavInsID.USE_CASE_CHOICE_CONFIRM, # Slots @@ -68,9 +74,10 @@ def test_menu_slot(firmware, backend, navigator, test_name): # UIF / Enable UIF for Signature # (back) # Reset / Long press 'Yes' -def test_menu_settings(firmware, backend, navigator, test_name): +def test_menu_settings(firmware: Firmware, backend: BackendInterface, navigator: Navigator, test_name: str) -> None: # Navigate in the main menu - if firmware.device == "nanos": + instructions: Sequence[InstructionType] + if firmware == Firmware.NANOS: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -144,7 +151,7 @@ def test_menu_settings(firmware, backend, navigator, test_name): NavInsID.BOTH_CLICK, # Validate ] - elif firmware.device.startswith("nano"): + elif firmware.is_nano: initial_instructions = [ NavInsID.RIGHT_CLICK, NavInsID.RIGHT_CLICK, @@ -154,17 +161,19 @@ def test_menu_settings(firmware, backend, navigator, test_name): NavInsID.BOTH_CLICK, # Key Template NavInsID.BOTH_CLICK, # Choose Key NavInsID.RIGHT_CLICK, # Decryption - NavInsID.BOTH_CLICK, # Key Decryption + NavInsID.RIGHT_CLICK, # Authentication + NavInsID.BOTH_CLICK, # Key Authentication NavInsID.RIGHT_CLICK, # Choose Type NavInsID.BOTH_CLICK, # (Select) NavInsID.RIGHT_CLICK, NavInsID.RIGHT_CLICK, NavInsID.RIGHT_CLICK, - NavInsID.BOTH_CLICK, # SECP 256K1 - NavInsID.RIGHT_CLICK, # Type SECP 256K1 + NavInsID.BOTH_CLICK, # SECP 256R1 + NavInsID.RIGHT_CLICK, # Type SECP 256R1 NavInsID.BOTH_CLICK, # Set Template NavInsID.RIGHT_CLICK, NavInsID.RIGHT_CLICK, + NavInsID.RIGHT_CLICK, NavInsID.BOTH_CLICK, # (Back) NavInsID.RIGHT_CLICK, @@ -198,27 +207,49 @@ def test_menu_settings(firmware, backend, navigator, test_name): NavInsID.RIGHT_CLICK, NavInsID.BOTH_CLICK, # Validate ] + else: initial_instructions = [ NavInsID.USE_CASE_HOME_SETTINGS, # Settings ] - instructions = [ - NavIns(NavInsID.TOUCH, (350, 130)), # Key Template - NavIns(NavInsID.TOUCH, (350, 300)), # Decryption - NavIns(NavInsID.TOUCH, (350, 390)), # SECP 256K1 - NavInsID.NAVIGATION_HEADER_TAP, # (Back) - NavIns(NavInsID.TOUCH, (350, 220)), # Seed mode - NavInsID.NAVIGATION_HEADER_TAP, # (Back) - NavIns(NavInsID.TOUCH, (350, 300)), # PIN mode - NavIns(NavInsID.TOUCH, (350, 130)), # On Screen - NavInsID.CENTERED_FOOTER_TAP, # Set default - NavInsID.NAVIGATION_HEADER_TAP, # (Back) - NavIns(NavInsID.TOUCH, (350, 390)), # UIF - NavIns(NavInsID.TOUCH, (350, 130)), # UIF for Signature - NavInsID.NAVIGATION_HEADER_TAP, # (Back) - NavIns(NavInsID.TOUCH, (350, 480)), # Reset - NavInsID.USE_CASE_REVIEW_CONFIRM, # Long press 'Yes' - ] + if firmware == Firmware.STAX: + instructions = [ + NavIns(NavInsID.TOUCH, (350, 130)), # Key Template + NavIns(NavInsID.TOUCH, (350, 390)), # Authentication + NavIns(NavInsID.TOUCH, (350, 390)), # SECP 256K1 + NavInsID.NAVIGATION_HEADER_TAP, # (Back) + NavIns(NavInsID.TOUCH, (350, 220)), # Seed mode + NavInsID.NAVIGATION_HEADER_TAP, # (Back) + NavIns(NavInsID.TOUCH, (350, 300)), # PIN mode + NavIns(NavInsID.TOUCH, (350, 130)), # On Screen + NavInsID.CENTERED_FOOTER_TAP, # Set default + NavInsID.NAVIGATION_HEADER_TAP, # (Back) + NavIns(NavInsID.TOUCH, (350, 390)), # UIF + NavIns(NavInsID.TOUCH, (350, 130)), # UIF for Signature + NavInsID.NAVIGATION_HEADER_TAP, # (Back) + NavIns(NavInsID.TOUCH, (350, 480)), # Reset + NavInsID.USE_CASE_CHOICE_CONFIRM, # Press 'Reset' + ] + + else: + instructions = [ + NavIns(NavInsID.TOUCH, (430, 130)), # Key Template + NavIns(NavInsID.TOUCH, (430, 420)), # Authentication + NavIns(NavInsID.TOUCH, (430, 320)), # SECP 256K1 + NavInsID.NAVIGATION_HEADER_TAP, # (Back) + NavIns(NavInsID.TOUCH, (430, 230)), # Seed mode + NavInsID.NAVIGATION_HEADER_TAP, # (Back) + NavIns(NavInsID.TOUCH, (430, 325)), # PIN mode + NavIns(NavInsID.TOUCH, (430, 140)), # On Screen + NavInsID.EXIT_FOOTER_TAP, # Set default + NavInsID.NAVIGATION_HEADER_TAP, # (Back) + NavIns(NavInsID.TOUCH, (430, 420)), # UIF + NavIns(NavInsID.TOUCH, (430, 130)), # UIF for Signature + NavInsID.NAVIGATION_HEADER_TAP, # (Back) + NavInsID.USE_CASE_SETTINGS_NEXT, # Next page + NavIns(NavInsID.TOUCH, (430, 130)), # Reset + NavInsID.USE_CASE_CHOICE_CONFIRM, # Press 'Reset' + ] # Use the app interface instead of raw interface client = CommandSender(backend) diff --git a/tests/test_password.py b/tests/test_password.py index c115602..92da47c 100644 --- a/tests/test_password.py +++ b/tests/test_password.py @@ -4,11 +4,16 @@ """ This module provides Ragger tests for Password feature """ +from pathlib import Path import pytest +from ragger.error import ExceptionRAPDU +from ragger.backend import BackendInterface +from ragger.firmware import Firmware +from ragger.navigator import Navigator + from application_client.command_sender import CommandSender from application_client.app_def import Errors, PassWord -from ragger.error import ExceptionRAPDU from utils import util_navigate @@ -22,7 +27,7 @@ (PassWord.PW3, "12345678"), ], ) -def test_verify(backend, pwd, value): +def test_verify(backend: BackendInterface, pwd: PassWord, value: str) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -49,7 +54,7 @@ def test_verify(backend, pwd, value): assert err.value.status & 0xFFF0 == 0x63c0 -def test_verify_wrong(backend): +def test_verify_wrong(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -60,7 +65,10 @@ def test_verify_wrong(backend): # In this test we check the card Password verification with Pinpad -def test_verify_confirm_accepted(firmware, backend, navigator, test_name): +def test_verify_confirm_accepted(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: Path) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -70,11 +78,14 @@ def test_verify_confirm_accepted(firmware, backend, navigator, test_name): # Check the status (Asynchronous) response = client.get_async_response() - assert response.status == Errors.SW_OK + assert response and response.status == Errors.SW_OK # In this test we check the Rejected card Password verification with Pinpad -def test_verify_confirm_refused(firmware, backend, navigator, test_name): +def test_verify_confirm_refused(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: Path) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -96,7 +107,7 @@ def test_verify_confirm_refused(firmware, backend, navigator, test_name): (PassWord.PW3, "12345678", "87654321"), ], ) -def test_change(backend, pwd, actual, new): +def test_change(backend: BackendInterface, pwd: PassWord, actual: str, new: str) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -114,7 +125,7 @@ def test_change(backend, pwd, actual, new): # In this test we check the Password Reset -def test_reset(backend): +def test_reset(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -136,7 +147,7 @@ def test_reset(backend): # In this test we check the Get Challenge -def test_challenge(backend): +def test_challenge(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) diff --git a/tests/test_seed.py b/tests/test_seed.py index 987bf67..2a7164a 100644 --- a/tests/test_seed.py +++ b/tests/test_seed.py @@ -5,8 +5,14 @@ This module provides Ragger tests for Signing feature with SEED mode """ import sys +from typing import Union import pytest +from Crypto.PublicKey.RSA import RsaKey +from Crypto.PublicKey.ECC import EccKey + +from ragger.backend import BackendInterface + from application_client.command_sender import CommandSender from application_client.app_def import Errors, DataObject, PassWord, PubkeyAlgo @@ -14,7 +20,7 @@ from utils import check_pincode, generate_key, get_key_attributes, KEY_TEMPLATES -def _gen_key(client: CommandSender, template: str): +def _gen_key(client: CommandSender, template: str) -> Union[RsaKey,EccKey]: # Verify PW3 (Admin) check_pincode(client, PassWord.PW3) @@ -50,7 +56,7 @@ def _gen_key(client: CommandSender, template: str): # "cv25519", # ECDH, SDK returns CX_EC_INVALID_CURVE ], ) -def test_seed_key(backend, template): +def test_seed_key(backend: BackendInterface, template: str) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) diff --git a/tests/test_sign.py b/tests/test_sign.py index 41ec111..ea465f5 100644 --- a/tests/test_sign.py +++ b/tests/test_sign.py @@ -9,6 +9,8 @@ from Crypto.Signature import pkcs1_15 from Crypto.Random import get_random_bytes +from ragger.backend import BackendInterface + from application_client.command_sender import CommandSender from application_client.app_def import Errors, DataObject, PassWord, PubkeyAlgo @@ -16,7 +18,7 @@ # In this test we check the key pair generation -def test_sign(backend): +def test_sign(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -43,7 +45,7 @@ def test_sign(backend): # In this test we check the key pair generation -def test_auth(backend): +def test_auth(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -63,8 +65,10 @@ def test_auth(backend): _verify_signature(client, hash_obj, DataObject.DO_AUT_KEY, rapdu.data) -def _verify_signature(client: CommandSender, hash_obj: SHA256.SHA256Hash, key_tag: DataObject, signature: bytes): - +def _verify_signature(client: CommandSender, + hash_obj: SHA256.SHA256Hash, + key_tag: DataObject, + signature: bytes) -> None: # Read the SIG pub Key pubkey: RsaKey = get_RSA_pub_key(client, key_tag) # Verify the signature diff --git a/tests/test_slot.py b/tests/test_slot.py index aff7eec..7778c1b 100644 --- a/tests/test_slot.py +++ b/tests/test_slot.py @@ -6,12 +6,14 @@ """ import pytest +from ragger.backend import BackendInterface + from application_client.command_sender import CommandSender from application_client.app_def import Errors, DataObject, PassWord from utils import check_pincode, generate_key -def test_slot(backend): +def test_slot(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) diff --git a/tests/test_template.py b/tests/test_template.py index 63325ab..a41c408 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -11,6 +11,8 @@ from Crypto.Random import get_random_bytes from Crypto.Signature import DSS +from ragger.backend import BackendInterface + from application_client.command_sender import CommandSender from application_client.app_def import Errors, DataObject, PassWord, PubkeyAlgo @@ -27,10 +29,9 @@ # "rsa4096", # Invalid signature? # "nistp256", # ECDSA, Pb with Pubkey generation? "ed25519", # EdDSA - # "cv25519", # ECDH, SDK returns CX_EC_INVALID_CURVE ], ) -def test_sign(backend, template): +def test_sign(backend: BackendInterface, template: str) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -67,16 +68,16 @@ def test_sign(backend, template): # Read the SIG pub Key and Verify the signature if key_algo == PubkeyAlgo.RSA: - pubkey = get_RSA_pub_key(client, DataObject.DO_SIG_KEY) - verifier = pkcs1_15.new(pubkey) - verifier.verify(hash_obj, rapdu.data) + pubRsakey = get_RSA_pub_key(client, DataObject.DO_SIG_KEY) + rsaVerifier = pkcs1_15.new(pubRsakey) + rsaVerifier.verify(hash_obj, rapdu.data) elif key_algo == PubkeyAlgo.ECDSA: - pubkey = get_ECDSA_pub_key(client, DataObject.DO_SIG_KEY) - verifier = DSS.new(pubkey, 'fips-186-3') + pubEcckey = get_ECDSA_pub_key(client, DataObject.DO_SIG_KEY) + verifier = DSS.new(pubEcckey, 'fips-186-3') verifier.verify(hash_obj, rapdu.data[2:]) elif key_algo == PubkeyAlgo.EDDSA: - pubkey = get_EDDSA_pub_key(client, DataObject.DO_SIG_KEY) - verifier = eddsa.new(pubkey, 'rfc8032') - verifier.verify(plain, rapdu.data) + pubEcckey = get_EDDSA_pub_key(client, DataObject.DO_SIG_KEY) + eddsaVerifier = eddsa.new(pubEcckey, 'rfc8032') + eddsaVerifier.verify(plain, rapdu.data) else: raise ValueError diff --git a/tests/test_version.py b/tests/test_version.py index 45ddc3c..3af0d98 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -4,17 +4,18 @@ """ This module provides Ragger tests for Version check """ +from ragger.utils.misc import get_current_app_name_and_version +from ragger.backend import BackendInterface + from application_client.command_sender import CommandSender from application_client.app_def import Errors, DataObject, PassWord from application_client.response_unpacker import unpack_info_response -from ragger.utils.misc import get_current_app_name_and_version - from utils import verify_name, verify_version, decode_tlv, check_pincode # In this test we check the App name and version -def test_check_version(backend): +def test_check_version(backend: BackendInterface) -> None: """Check version and name""" # Send the APDU @@ -26,7 +27,7 @@ def test_check_version(backend): # In this test we check the Card activation -def test_activate(backend): +def test_activate(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -36,7 +37,7 @@ def test_activate(backend): # In this test we get the Card Application ID value -def test_info(backend): +def test_info(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -57,7 +58,7 @@ def test_info(backend): # In this test we test the User Data information -def test_user(backend): +def test_user(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) @@ -89,7 +90,7 @@ def test_user(backend): assert rapdu.data.hex()[20:28] == serial -def _check_card_value(client, tag: DataObject, value: str): +def _check_card_value(client: CommandSender, tag: DataObject, value: str) -> None: rapdu = client.put_data(tag, value.encode("utf-8")) assert rapdu.status == Errors.SW_OK @@ -101,7 +102,7 @@ def _check_card_value(client, tag: DataObject, value: str): assert rvalue == value -def _check_user_value(client, tag: DataObject, value: str): +def _check_user_value(client: CommandSender, tag: DataObject, value: str) -> None: rapdu = client.put_data(tag, value.encode("utf-8")) assert rapdu.status == Errors.SW_OK diff --git a/tests/usage.md b/tests/usage.md index 75e9664..f20bacc 100644 --- a/tests/usage.md +++ b/tests/usage.md @@ -21,7 +21,7 @@ docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest cd docker run --user "$(id -u)":"$(id -g)" --rm -ti -v "$(realpath .):/app" --privileged -v "/dev/bus/usb:/dev/bus/usb" ledger-app-builder-lite:latest -make clean && make BOLOS_SDK=$_SDK # replace with one of [NANOS, NANOX, NANOSP, STAX] +make clean && make BOLOS_SDK=$_SDK # replace with one of [NANOS, NANOX, NANOSP, STAX, FLEX] exit ``` @@ -45,7 +45,7 @@ docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest cd app-/ docker run --user "$(id -u)":"$(id -g)" --rm -ti -v "$(realpath .):/app" --privileged -v "/dev/bus/usb:/dev/bus/usb" ledger-app-builder-lite:latest -make clean && make BOLOS_SDK=$_SDK load # replace with one of [NANOS, NANOX, NANOSP, STAX] +make clean && make BOLOS_SDK=$_SDK load # replace with one of [NANOS, NANOX, NANOSP, STAX, FLEX] exit ``` @@ -73,7 +73,7 @@ Custom pytest options ```shell --full Run full tests - --device Run the test on the specified device [nanos,nanox,nanosp,stax,all]. This parameter is mandatory + --device Run the test on the specified device [nanos,nanox,nanosp,stax,flex,all]. This parameter is mandatory --backend Run the tests against the backend [speculos, ledgercomm, ledgerwallet]. Speculos is the default --display On Speculos, enables the display of the app screen using QT --golden_run Pn Speculos, screen comparison functions will save the current screen instead of comparing diff --git a/tests/utils.py b/tests/utils.py index 5d5e770..4b246da 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -43,7 +43,7 @@ def util_navigate( assert text valid_instr: list[NavIns | NavInsID] = [] - if firmware.device == "nanos": + if firmware == Firmware.NANOS: text, txt_cfg = text.split("_") nav_inst = NavInsID.RIGHT_CLICK if txt_cfg == "Yes": @@ -53,7 +53,7 @@ def util_navigate( else: raise ValueError(f'Wrong text "{text}"') - elif firmware.device.startswith("nano"): + elif firmware.is_nano: text = text.split("_")[1] nav_inst = NavInsID.RIGHT_CLICK valid_instr.append(NavInsID.BOTH_CLICK)