diff --git a/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h b/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h index 2cd5c9b8f5..d62327847f 100644 --- a/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h +++ b/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h @@ -150,6 +150,21 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0( mod_trezorcrypto_se_thd89_get_session_state_obj, mod_trezorcrypto_se_thd89_get_session_state); +/// def get_session_current_id() -> bytes: +/// """ +/// get current session id. +/// """ +STATIC mp_obj_t mod_trezorcrypto_se_thd89_get_session_current_id(void) { + uint8_t session_id[32] = {0}; + if (!se_session_get_current_id(session_id)) { + return mp_const_none; + } + return mp_obj_new_bytes(session_id, 32); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0( + mod_trezorcrypto_se_thd89_get_session_current_id_obj, + mod_trezorcrypto_se_thd89_get_session_current_id); + /// def session_is_open() -> bool: /// """ /// get current session secret state. @@ -1084,6 +1099,42 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1( mod_trezorcrypto_se_thd89_check_passphrase_btc_test_address_obj, mod_trezorcrypto_se_thd89_check_passphrase_btc_test_address); +/// def change_pin_passphrase(old_pin: str, new_pin: str) -> bool: +/// """ +/// Change the PIN of an existing passphrase entry. +/// Returns True on success, False on failure. +/// """ +STATIC mp_obj_t mod_trezorcrypto_se_thd89_change_pin_passphrase( + mp_obj_t old_pin, mp_obj_t new_pin) { + mp_buffer_info_t old_pin_buf = {0}; + mp_get_buffer_raise(old_pin, &old_pin_buf, MP_BUFFER_READ); + + mp_buffer_info_t new_pin_buf = {0}; + mp_get_buffer_raise(new_pin, &new_pin_buf, MP_BUFFER_READ); + + if (old_pin_buf.len < 6 || old_pin_buf.len > PIN_MAX_LENGTH) { + mp_raise_ValueError("Old PIN length must be between 6 and 50 characters"); + } + + if (new_pin_buf.len < 6 || new_pin_buf.len > PIN_MAX_LENGTH) { + mp_raise_ValueError("New PIN length must be between 6 and 50 characters"); + } + + if (old_pin_buf.len == new_pin_buf.len) { + if (memcmp(old_pin_buf.buf, new_pin_buf.buf, old_pin_buf.len) == 0) { + mp_raise_ValueError("New PIN cannot be the same as old PIN"); + } + } + + secbool ret = se_change_pin_passphrase((const char *)old_pin_buf.buf, + (const char *)new_pin_buf.buf); + + return ret ? mp_const_true : mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2( + mod_trezorcrypto_se_thd89_change_pin_passphrase_obj, + mod_trezorcrypto_se_thd89_change_pin_passphrase); + /// FIDO2_CRED_COUNT_MAX: int STATIC const mp_rom_map_elem_t mod_trezorcrypto_se_thd89_globals_table[] = { @@ -1100,6 +1151,8 @@ STATIC const mp_rom_map_elem_t mod_trezorcrypto_se_thd89_globals_table[] = { MP_ROM_PTR(&mod_trezorcrypto_se_thd89_end_session_obj)}, {MP_ROM_QSTR(MP_QSTR_get_session_state), MP_ROM_PTR(&mod_trezorcrypto_se_thd89_get_session_state_obj)}, + {MP_ROM_QSTR(MP_QSTR_get_session_current_id), + MP_ROM_PTR(&mod_trezorcrypto_se_thd89_get_session_current_id_obj)}, {MP_ROM_QSTR(MP_QSTR_session_is_open), MP_ROM_PTR(&mod_trezorcrypto_se_thd89_session_is_open_obj)}, {MP_ROM_QSTR(MP_QSTR_get_session_type), @@ -1169,6 +1222,8 @@ STATIC const mp_rom_map_elem_t mod_trezorcrypto_se_thd89_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_check_passphrase_btc_test_address), MP_ROM_PTR( &mod_trezorcrypto_se_thd89_check_passphrase_btc_test_address_obj)}, + {MP_ROM_QSTR(MP_QSTR_change_pin_passphrase), + MP_ROM_PTR(&mod_trezorcrypto_se_thd89_change_pin_passphrase_obj)}, {MP_ROM_QSTR(MP_QSTR_USER_PIN_ENTERED), MP_ROM_INT(USER_PIN_ENTERED)}, {MP_ROM_QSTR(MP_QSTR_PASSPHRASE_PIN_ENTERED), MP_ROM_INT(PASSPHRASE_PIN_ENTERED)}, diff --git a/core/embed/trezorhal/se_thd89.c b/core/embed/trezorhal/se_thd89.c index 9a342ec5ea..3d0b0b878c 100644 --- a/core/embed/trezorhal/se_thd89.c +++ b/core/embed/trezorhal/se_thd89.c @@ -3,6 +3,7 @@ #include "common.h" #include "flash.h" +#include "irq.h" #include "memzero.h" #include "secbool.h" @@ -263,15 +264,30 @@ static secbool se_transmit_mac_ex(uint8_t addr, uint8_t *session_key, secbool se_transmit_mac(uint8_t ins, uint8_t p1, uint8_t p2, uint8_t *data, uint16_t data_len, uint8_t *recv, uint16_t *recv_len) { - return se_transmit_mac_ex(THD89_MASTER_ADDRESS, se_session_key, ins, p1, p2, - data, data_len, recv, recv_len); + uint32_t irq = disable_irq(); + thd89_irq_nest++; + secbool result = se_transmit_mac_ex(THD89_MASTER_ADDRESS, se_session_key, ins, + p1, p2, data, data_len, recv, recv_len); + thd89_irq_nest--; + if (thd89_irq_nest == 0) { + enable_irq(irq); + } + return result; } secbool se_fp_transmit_mac(uint8_t ins, uint8_t p1, uint8_t p2, uint8_t *data, uint16_t data_len, uint8_t *recv, uint16_t *recv_len) { - return se_transmit_mac_ex(THD89_FINGER_ADDRESS, se_fp_session_key, ins, p1, - p2, data, data_len, recv, recv_len); + uint32_t irq = disable_irq(); + thd89_irq_nest++; + secbool result = + se_transmit_mac_ex(THD89_FINGER_ADDRESS, se_fp_session_key, ins, p1, p2, + data, data_len, recv, recv_len); + thd89_irq_nest--; + if (thd89_irq_nest == 0) { + enable_irq(irq); + } + return result; } secbool se_random_encrypted(uint8_t *rand, uint16_t len) { @@ -1478,6 +1494,47 @@ secbool se_get_pin_passphrase_space(uint8_t *space) { return sectrue; } +secbool se_change_pin_passphrase_ex(uint8_t addr, uint8_t *session_key, + const char *old_pin, const char *new_pin) { + uint8_t buf[128]; + uint8_t resp[1]; + uint16_t resp_len = 1; + + if (strlen(old_pin) < 6 || strlen(old_pin) > PIN_MAX_LENGTH || + strlen(new_pin) < 6 || strlen(new_pin) > PIN_MAX_LENGTH) { + return secfalse; + } + + buf[0] = strlen(old_pin); + memcpy(buf + 1, (uint8_t *)old_pin, strlen(old_pin)); + buf[1 + strlen(old_pin)] = strlen(new_pin); + memcpy(buf + 1 + strlen(old_pin) + 1, (uint8_t *)new_pin, strlen(new_pin)); + + if (!se_transmit_mac_ex(addr, session_key, SE_INS_PIN, 0x00, 0x0E, buf, + 1 + strlen(old_pin) + 1 + strlen(new_pin), resp, + &resp_len)) { + return secfalse; + } + if (resp[0] == PIN_SUCCESS) { + return sectrue; + } + return secfalse; +} + +secbool se_change_pin_passphrase(const char *old_pin, const char *new_pin) { + secbool result = se_change_pin_passphrase_ex( + THD89_MASTER_ADDRESS, se_session_key, old_pin, new_pin); + if (result == sectrue) { + secbool fp_result = se_change_pin_passphrase_ex( + THD89_FINGER_ADDRESS, se_fp_session_key, old_pin, new_pin); + if (fp_result == sectrue) { + return sectrue; + } + return secfalse; + } + return secfalse; +} + pin_result_t se_get_pin_result_type(void) { return pin_result_type; } pin_result_t se_get_pin_passphrase_ret(void) { return pin_passphrase_ret; } @@ -1959,6 +2016,14 @@ secbool se_session_get_type(uint8_t *type) { return sectrue; } +secbool se_session_get_current_id(uint8_t id[32]) { + uint16_t recv_len = 32; + if (!se_transmit_mac(SE_INS_SESSION, 0x00, 0x0A, NULL, 0, id, &recv_len)) { + return secfalse; + } + return sectrue; +} + secbool se_node_sign_digest(const uint8_t *hash, uint8_t *sig, uint8_t *by) { uint8_t resp[68]; uint16_t resp_len = sizeof(resp); diff --git a/core/embed/trezorhal/se_thd89.h b/core/embed/trezorhal/se_thd89.h index 94e3a14762..3c53c96694 100644 --- a/core/embed/trezorhal/se_thd89.h +++ b/core/embed/trezorhal/se_thd89.h @@ -40,6 +40,7 @@ typedef enum { PIN_TYPE_USER_AND_PASSPHRASE_PIN, PIN_TYPE_PASSPHRASE_PIN, PIN_TYPE_PASSPHRASE_PIN_CHECK, + PIN_TYPE_USER_AND_PASSPHRASE_PIN_CHECK, PIN_TYPE_MAX } pin_type_t; @@ -120,6 +121,7 @@ secbool se_delete_pin_passphrase(const char *passphrase_pin, bool *current); pin_result_t se_get_pin_passphrase_ret(void); secbool se_get_pin_passphrase_space(uint8_t *space); secbool se_check_passphrase_btc_test_address(const char *address); +secbool se_change_pin_passphrase(const char *old_pin, const char *new_pin); secbool se_clearSecsta(void); secbool se_getSecsta(void); secbool se_set_u2f_counter(uint32_t u2fcounter); @@ -137,6 +139,7 @@ secbool se_session_is_open(void); secbool se_sessionClose(void); secbool se_sessionClear(void); secbool se_session_get_type(uint8_t *type); +secbool se_session_get_current_id(uint8_t id[32]); secbool se_set_public_region(uint16_t offset, const void *val_dest, uint16_t len); diff --git a/core/embed/trezorhal/thd89.c b/core/embed/trezorhal/thd89.c index 0d50b17074..1b1087d2ac 100644 --- a/core/embed/trezorhal/thd89.c +++ b/core/embed/trezorhal/thd89.c @@ -538,8 +538,8 @@ int i2c_master_recive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, } } -secbool thd89_transmit_ex(uint8_t addr, uint8_t *cmd, uint16_t len, - uint8_t *resp, uint16_t *resp_len) { +static secbool _thd89_transmit_ex(uint8_t addr, uint8_t *cmd, uint16_t len, + uint8_t *resp, uint16_t *resp_len) { int ret = 0; char err_info[64] = {0}; uint32_t irq = disable_irq(); @@ -553,7 +553,6 @@ secbool thd89_transmit_ex(uint8_t addr, uint8_t *cmd, uint16_t len, return secfalse; } - delay_ms(1); irq = disable_irq(); ret = i2c_master_recive(&i2c_handle_se, addr, resp, resp_len, I2C_RECV_TIMEOUT); @@ -577,6 +576,20 @@ secbool thd89_transmit_ex(uint8_t addr, uint8_t *cmd, uint16_t len, return sectrue; } +int thd89_irq_nest = 0; + +secbool thd89_transmit_ex(uint8_t addr, uint8_t *cmd, uint16_t len, + uint8_t *resp, uint16_t *resp_len) { + uint32_t irq = disable_irq(); + thd89_irq_nest++; + secbool result = _thd89_transmit_ex(addr, cmd, len, resp, resp_len); + thd89_irq_nest--; + if (thd89_irq_nest == 0) { + enable_irq(irq); + } + return result; +} + secbool thd89_transmit(uint8_t *cmd, uint16_t len, uint8_t *resp, uint16_t *resp_len) { return thd89_transmit_ex(THD89_MASTER_ADDRESS, cmd, len, resp, resp_len); diff --git a/core/embed/trezorhal/thd89.h b/core/embed/trezorhal/thd89.h index e116c66785..a1b991cba9 100644 --- a/core/embed/trezorhal/thd89.h +++ b/core/embed/trezorhal/thd89.h @@ -11,6 +11,8 @@ #define THD89_MASTER_ADDRESS THD89_1ST_ADDRESS #define THD89_FINGER_ADDRESS THD89_4TH_ADDRESS +extern int thd89_irq_nest; + void thd89_io_init(void); void thd89_init(void); void thd89_power_up(bool up); diff --git a/core/mocks/generated/trezorcrypto/se_thd89.pyi b/core/mocks/generated/trezorcrypto/se_thd89.pyi index 81490c8de5..90bc0223e6 100644 --- a/core/mocks/generated/trezorcrypto/se_thd89.pyi +++ b/core/mocks/generated/trezorcrypto/se_thd89.pyi @@ -53,6 +53,13 @@ def get_session_state() -> bytes: """ +# extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h +def get_session_current_id() -> bytes: + """ + get current session id. + """ + + # extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h def session_is_open() -> bool: """ @@ -331,4 +338,12 @@ def check_passphrase_btc_test_address(address: str) -> bool: """ Check if the passphrase is a valid Bitcoin test address. """ + + +# extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h +def change_pin_passphrase(old_pin: str, new_pin: str) -> bool: + """ + Change the PIN of an existing passphrase entry. + Returns True on success, False on failure. + """ FIDO2_CRED_COUNT_MAX: int diff --git a/core/src/apps/base.py b/core/src/apps/base.py index 6fa310e2d9..f4028561af 100644 --- a/core/src/apps/base.py +++ b/core/src/apps/base.py @@ -247,6 +247,7 @@ def get_onekey_features() -> OnekeyFeatures: async def handle_Initialize( ctx: wire.Context | wire.QRContext, msg: Initialize ) -> Features: + session_id_in_msg = getattr(msg, "session_id", None) has_attach = ( hasattr(msg, "is_contains_attach") and msg.is_contains_attach is not None ) @@ -262,13 +263,20 @@ async def handle_Initialize( else: passphrase_state = None - session_id_in_msg = getattr(msg, "session_id", None) if passphrase_state and se_thd89.check_passphrase_btc_test_address( passphrase_state ): - session_id = storage.cache.start_session() + session_id = se_thd89.get_session_current_id() + if device_is_unlocked() and not storage.device.is_passphrase_pin_enabled(): + session_id = storage.cache.start_session(session_id_in_msg) + elif session_id_in_msg == session_id: + session_id = storage.cache.start_session(session_id_in_msg) + else: + session_id = storage.cache.start_session() elif has_attach and session_id_in_msg is not None and passphrase_state is None: session_id = storage.cache.start_session() + elif device_is_unlocked() and storage.device.is_passphrase_pin_enabled(): + session_id = storage.cache.start_session() else: session_id = storage.cache.start_session(session_id_in_msg) @@ -606,6 +614,7 @@ async def unlock_device( ctx: wire.GenericContext = wire.DUMMY_CONTEXT, pin_use_type: int = PinType.USER_AND_PASSPHRASE_PIN, attach_wall_only: bool = False, + allow_fingerprint: bool = True, ) -> None: from apps.common.request_pin import verify_user_pin, verify_user_fingerprint @@ -627,11 +636,13 @@ async def unlock_device( close_others=False, pin_use_type=pin_use_type_int, attach_wall_only=attach_wall_only, + allow_fingerprint=allow_fingerprint, ) verify_finger = verify_user_fingerprint(ctx) racer = loop.race(verify_pin, verify_finger) await racer if verify_finger in racer.finished: + from trezor.lvglui.scrs.pinscreen import InputPin pin_wind = InputPin.get_window_if_visible() @@ -698,25 +709,15 @@ async def handle_GetPassphraseState( if not device_is_unlocked(): await unlock_device(ctx, pin_use_type=PinType.USER_AND_PASSPHRASE_PIN) - session_id = storage.cache.start_session() - - from trezor.lvglui.scrs import fingerprints - if ( - fingerprints.is_available() - and fingerprints.is_unlocked() - and not config.is_unlocked() - ): - if storage.device.is_passphrase_pin_enabled(): - storage.device.set_passphrase_pin_enabled(False) + session_id = se_thd89.get_session_current_id() + if session_id is None or session_id == b"": + session_id = storage.cache.start_session() import utime from apps.bitcoin.get_address import get_address as btc_get_address try: - session_id = storage.cache.get_session_id() - if session_id is None or session_id == b"": - session_id = storage.cache.start_session() utime.sleep_ms(500) fixed_path = "m/44'/1'/0'/0/0" address_msg = messages.GetAddress( @@ -727,9 +728,6 @@ async def handle_GetPassphraseState( ) address_obj = await btc_get_address(ctx, address_msg) - session_id = storage.cache.get_session_id() - if session_id is None or session_id == b"": - session_id = storage.cache.start_session() is_attach_to_pin_state = passphrase.is_passphrase_pin_enabled() return PassphraseState( passphrase_state=address_obj.address, diff --git a/core/src/apps/common/passphrase.py b/core/src/apps/common/passphrase.py index 5d027833ad..e246507ef5 100644 --- a/core/src/apps/common/passphrase.py +++ b/core/src/apps/common/passphrase.py @@ -81,7 +81,10 @@ async def _request_on_host(ctx: wire.Context) -> str: from apps.common.pin_constants import PinType await unlock_device( - ctx, pin_use_type=PinType.PASSPHRASE_PIN, attach_wall_only=True + ctx, + pin_use_type=PinType.PASSPHRASE_PIN, + attach_wall_only=True, + allow_fingerprint=False, ) storage.cache.start_session() return "" diff --git a/core/src/apps/common/pin_constants.py b/core/src/apps/common/pin_constants.py index d1c57178e3..23c1d91ad3 100644 --- a/core/src/apps/common/pin_constants.py +++ b/core/src/apps/common/pin_constants.py @@ -20,7 +20,8 @@ class PinType: USER_AND_PASSPHRASE_PIN = 2 PASSPHRASE_PIN = 3 PASSPHRASE_PIN_CHECK = 4 - MAX = 5 + USER_AND_PASSPHRASE_PIN_CHECK = 5 + MAX = 6 class AttachCommon: diff --git a/core/src/apps/common/request_pin.py b/core/src/apps/common/request_pin.py index 147558caa4..078156a485 100644 --- a/core/src/apps/common/request_pin.py +++ b/core/src/apps/common/request_pin.py @@ -6,7 +6,8 @@ from trezor import config, loop, wire from trezor.lvglui.i18n import gettext as _, keys as i18n_keys from trezor.lvglui.lv_colors import lv_colors -from trezor.lvglui.scrs import fingerprints +from trezor.lvglui.scrs import fingerprints, font_GeistRegular30, font_GeistSemiBold64 +from trezor.lvglui.scrs.common import FullSizeWindow, lv from apps.common.pin_constants import PinResult, PinType @@ -164,7 +165,11 @@ async def verify_user_pin( if not config.is_unlocked(): try: verified, usertype = config.unlock(pin, salt, pin_use_type) - if verified: + if verified and pin_use_type in ( + PinType.USER, + PinType.PASSPHRASE_PIN, + PinType.USER_AND_PASSPHRASE_PIN, + ): if usertype == PinResult.PASSPHRASE_PIN_ENTERED: device.set_passphrase_pin_enabled(True) elif usertype == PinResult.USER_PIN_ENTERED: @@ -177,7 +182,11 @@ async def verify_user_pin( verified, usertype = config.check_pin( pin, salt, pin_use_type, auto_vibrate=True ) - if verified: + if verified and pin_use_type in ( + PinType.USER, + PinType.PASSPHRASE_PIN, + PinType.USER_AND_PASSPHRASE_PIN, + ): if usertype == PinResult.PASSPHRASE_PIN_ENTERED: device.set_passphrase_pin_enabled(True) elif usertype == PinResult.USER_PIN_ENTERED: @@ -222,7 +231,11 @@ async def verify_user_pin( except Exception: raise wire.PinCancelled("cal cale ..") - if verified: + if verified and pin_use_type in ( + PinType.USER, + PinType.PASSPHRASE_PIN, + PinType.USER_AND_PASSPHRASE_PIN, + ): if usertype == PinResult.PASSPHRASE_PIN_ENTERED: device.set_passphrase_pin_enabled(True) elif usertype == PinResult.USER_PIN_ENTERED: @@ -249,9 +262,6 @@ async def verify_user_fingerprint( return if await fingerprints.request(): fingerprints.unlock() - import storage.device as device - - device.set_passphrase_pin_enabled(False) if re_loop: loop.clear() elif callback: @@ -287,6 +297,85 @@ async def error_pin_used(ctx: wire.Context) -> NoReturn: assert False +async def passphrase_pin_used(ctx: wire.Context): + screen = FullSizeWindow( + None, + None, + confirm_text=_(i18n_keys.BUTTON__OVERWRITE), + anim_dir=0, + ) + + close_btn = lv.btn(screen) + close_btn.set_size(48, 48) + close_btn.align(lv.ALIGN.TOP_RIGHT, -12, 56) + close_btn.set_style_bg_color(lv_colors.BLACK, 0) + close_btn.set_style_bg_opa(0, 0) + close_btn.set_style_border_width(0, 0) + close_btn.set_style_shadow_width(0, 0) + close_btn.add_flag(lv.obj.FLAG.CLICKABLE) + close_btn.set_ext_click_area(100) + + close_img = lv.img(close_btn) + close_img.set_src("A:/res/nav-icon.png") + close_img.center() + + title_label = lv.label(screen.content_area) + title_label.set_text(_(i18n_keys.PASSPHRASE__PIN_USED)) + title_label.set_style_text_font(font_GeistSemiBold64, 0) + title_label.set_style_text_color(lv_colors.WHITE, 0) + title_label.set_style_text_letter_space(-6, 0) + title_label.set_style_text_line_space(-6, 0) + title_label.set_long_mode(lv.label.LONG.WRAP) + title_label.set_size(456, lv.SIZE.CONTENT) + title_label.align(lv.ALIGN.TOP_MID, 0, 72) + + if hasattr(screen, "subtitle"): + screen.subtitle.delete() + + subtitle_label = lv.label(screen.content_area) + subtitle_label.set_text(_(i18n_keys.TITLE__PIN_ALREADY_USED_DESC)) + subtitle_label.set_style_text_font(font_GeistRegular30, 0) + subtitle_label.set_style_text_color(lv_colors.LIGHT_GRAY, 0) + subtitle_label.set_style_text_letter_space(-2, 0) + subtitle_label.set_style_text_line_space(5, 0) + subtitle_label.set_long_mode(lv.label.LONG.WRAP) + subtitle_label.set_size(456, lv.SIZE.CONTENT) + subtitle_label.align_to(title_label, lv.ALIGN.OUT_BOTTOM_MID, 0, 16) + + # Set confirm button text color to gray + if hasattr(screen, "btn_yes"): + screen.btn_yes.enable(lv_colors.ONEKEY_GRAY_3, text_color=lv_colors.WHITE) + + processing = False + + def on_close_clicked(e): + nonlocal processing + if e.code == lv.EVENT.CLICKED and not processing: + processing = True + screen.show_dismiss_anim() + screen.channel.publish(0) + + close_btn.add_event_cb(on_close_clicked, lv.EVENT.CLICKED, None) + + screen.btn_layout_ver() + result = await ctx.wait(screen.request()) + return result + + +# async def passphrase_pin_used(ctx: wire.Context) -> NoReturn: +# from trezor.ui.layouts import show_error_and_raise + +# await show_error_and_raise( +# ctx, +# "warning_wrong_pin", +# header=_(i18n_keys.PASSPHRASE__PIN_USED), +# content=_(i18n_keys.PASSPHRASE__PIN_USED_DESC), #i18n待更改 +# red=True, +# exc=wire.PinInvalid, +# ) +# assert False + + async def error_pin_matches_wipe_code(ctx: wire.Context) -> NoReturn: from trezor.ui.layouts import show_error_and_raise diff --git a/core/src/apps/management/apply_settings.py b/core/src/apps/management/apply_settings.py index f6f32aba9e..7a3183fc8f 100644 --- a/core/src/apps/management/apply_settings.py +++ b/core/src/apps/management/apply_settings.py @@ -75,6 +75,12 @@ async def apply_settings(ctx: wire.Context, msg: ApplySettings) -> Success: await require_confirm_change_passphrase(ctx, msg.use_passphrase) storage.device.set_passphrase_enabled(msg.use_passphrase) + if not msg.use_passphrase and storage.device.is_passphrase_pin_enabled(): + from apps.base import lock_device + + storage.device.set_passphrase_pin_enabled(False) + lock_device() + if msg.passphrase_always_on_device is not None: if not storage.device.is_passphrase_enabled(): raise wire.DataError("Passphrase is not enabled") diff --git a/core/src/apps/management/change_pin.py b/core/src/apps/management/change_pin.py index 46a96fc311..2919ccac06 100644 --- a/core/src/apps/management/change_pin.py +++ b/core/src/apps/management/change_pin.py @@ -2,8 +2,10 @@ from storage.device import is_initialized from trezor import config, wire +from trezor.crypto import se_thd89 from trezor.lvglui.i18n import gettext as _, keys as i18n_keys from trezor.lvglui.lv_colors import lv_colors +from trezor.lvglui.scrs.pinscreen import request_change_passphrase_pin from trezor.messages import Success from trezor.ui.layouts import confirm_action, show_success @@ -11,10 +13,14 @@ error_pin_invalid, error_pin_matches_wipe_code, error_pin_used, + passphrase_pin_used, request_pin_and_sd_salt, request_pin_confirm, ) +PIN_CANCEL = 0 +PIN_OVERWRITE = 1 + if TYPE_CHECKING: from typing import Awaitable @@ -24,64 +30,151 @@ async def change_pin(ctx: wire.Context, msg: ChangePin) -> Success: if not is_initialized(): raise wire.NotInitialized("Device is not initialized") - # confirm that user wants to change the pin await require_confirm_change_pin(ctx, msg) - # get old pin curpin, salt = await request_pin_and_sd_salt( ctx, _(i18n_keys.TITLE__ENTER_OLD_PIN), allow_fingerprint=False, - standy_wall_only=True, ) - # if changing pin, pre-check the entered pin before getting new pin from apps.common.pin_constants import PinType, PinResult if curpin and not msg.remove: - verified = config.check_pin(curpin, salt, PinType.USER_CHECK)[0] - if not verified: - await error_pin_invalid(ctx) - - # get new pin - if not msg.remove: - newpin = await request_pin_confirm( - ctx, show_tip=(not bool(curpin)), allow_fingerprint=False - ) - else: - newpin = "" - - if newpin: verified, usertype = config.check_pin( - newpin, salt, PinType.PASSPHRASE_PIN_CHECK + curpin, salt, PinType.USER_AND_PASSPHRASE_PIN_CHECK ) - if usertype == PinResult.PASSPHRASE_PIN_ENTERED: - return await error_pin_used(ctx) - - # write into storage - if not config.change_pin(curpin, newpin, salt, salt): - if newpin: - await error_pin_matches_wipe_code(ctx) - else: + if not verified: await error_pin_invalid(ctx) - - if newpin: - if curpin: - msg_screen = _(i18n_keys.SUBTITLE__SET_PIN_PIN_CHANGED) - msg_wire = _(i18n_keys.TITLE__PIN_CHANGED) - else: - msg_screen = _(i18n_keys.SUBTITLE__SETUP_SET_PIN_PIN_ENABLED) - msg_wire = _(i18n_keys.TITLE__PIN_ENABLED) - else: - msg_screen = _(i18n_keys.SUBTITLE__SET_PIN_PIN_DISABLED) - msg_wire = _(i18n_keys.TITLE__PIN_DISABLED) - - await show_success( - ctx, - "success_pin", - msg_screen, - header=msg_wire, - button=_(i18n_keys.BUTTON__DONE), - ) - return Success(message=msg_wire) + if usertype == PinResult.USER_PIN_ENTERED: + if not msg.remove: + newpin = await request_pin_confirm( + ctx, show_tip=(not bool(curpin)), allow_fingerprint=False + ) + else: + newpin = "" + is_current = False + remove_result = False + if newpin: + verified, usertype = config.check_pin( + newpin, salt, PinType.PASSPHRASE_PIN_CHECK + ) + if usertype == PinResult.PASSPHRASE_PIN_ENTERED: + result = await passphrase_pin_used(ctx) + if result == PIN_CANCEL: + return Success(message="Operation cancelled") + elif result == PIN_OVERWRITE: + passphrase_pin_str = ( + str(newpin) if not isinstance(newpin, str) else newpin + ) + ( + remove_result, + is_current, + ) = se_thd89.delete_pin_passphrase(passphrase_pin_str) + # write into storage + if not config.change_pin(curpin, newpin, salt, salt): + if newpin: + await error_pin_matches_wipe_code(ctx) + else: + await error_pin_invalid(ctx) + if remove_result and is_current: + verified, usertype = config.check_pin(newpin, salt, PinType.USER) + if usertype == PinResult.USER_PIN_ENTERED: + import storage.device + + storage.device.set_passphrase_pin_enabled(False) + + if newpin: + if curpin: + msg_screen = _(i18n_keys.SUBTITLE__SET_PIN_PIN_CHANGED) + msg_wire = _(i18n_keys.TITLE__PIN_CHANGED) + else: + msg_screen = _(i18n_keys.SUBTITLE__SETUP_SET_PIN_PIN_ENABLED) + msg_wire = _(i18n_keys.TITLE__PIN_ENABLED) + else: + msg_screen = _(i18n_keys.SUBTITLE__SET_PIN_PIN_DISABLED) + msg_wire = _(i18n_keys.TITLE__PIN_DISABLED) + + await show_success( + ctx, + "success_pin", + msg_screen, + header=msg_wire, + button=_(i18n_keys.BUTTON__DONE), + ) + return Success(message=msg_wire) + elif usertype == PinResult.PASSPHRASE_PIN_ENTERED: + # get new pin + if not msg.remove: + newpin = await request_change_passphrase_pin(ctx) + else: + newpin = "" + if newpin: + verified, usertype = config.check_pin( + newpin, salt, PinType.USER_AND_PASSPHRASE_PIN_CHECK + ) + if usertype == PinResult.USER_PIN_ENTERED: + return await error_pin_used(ctx) + if usertype == PinResult.PASSPHRASE_PIN_ENTERED: + if newpin == curpin: + await show_success( + ctx, + "success_pin", + _(i18n_keys.SUBTITLE__SET_PIN_PIN_CHANGED), + header=_(i18n_keys.TITLE__PIN_CHANGED), + button=_(i18n_keys.BUTTON__DONE), + ) + return Success(message=_(i18n_keys.TITLE__PIN_CHANGED)) + result = await passphrase_pin_used(ctx) + if result == PIN_CANCEL: + return Success(message="Operation cancelled") + elif result == PIN_OVERWRITE: + # Define messages for passphrase PIN change + if curpin and not msg.remove: + msg_screen = _(i18n_keys.SUBTITLE__SET_PIN_PIN_CHANGED) + msg_wire = _(i18n_keys.TITLE__PIN_CHANGED) + elif not curpin and not msg.remove: + msg_screen = _( + i18n_keys.SUBTITLE__SETUP_SET_PIN_PIN_ENABLED + ) + msg_wire = _(i18n_keys.TITLE__PIN_ENABLED) + else: + msg_screen = _(i18n_keys.SUBTITLE__SET_PIN_PIN_DISABLED) + msg_wire = _(i18n_keys.TITLE__PIN_DISABLED) + + result = se_thd89.change_pin_passphrase(curpin, newpin) + + await show_success( + ctx, + "success_pin", + msg_screen, + header=msg_wire, + button=_(i18n_keys.BUTTON__DONE), + ) + return Success(message=msg_wire) + else: + if curpin and not msg.remove: + msg_screen = _(i18n_keys.SUBTITLE__SET_PIN_PIN_CHANGED) + msg_wire = _(i18n_keys.TITLE__PIN_CHANGED) + elif not curpin and not msg.remove: + msg_screen = _(i18n_keys.SUBTITLE__SETUP_SET_PIN_PIN_ENABLED) + msg_wire = _(i18n_keys.TITLE__PIN_ENABLED) + else: + msg_screen = _(i18n_keys.SUBTITLE__SET_PIN_PIN_DISABLED) + msg_wire = _(i18n_keys.TITLE__PIN_DISABLED) + + result = se_thd89.change_pin_passphrase(curpin, newpin) + if result: + await show_success( + ctx, + "success_pin", + msg_screen, + header=msg_wire, + button=_(i18n_keys.BUTTON__DONE), + ) + return Success(message=msg_wire) + else: + return await error_pin_used(ctx) + + return Success(message="PIN operation completed") def require_confirm_change_pin(ctx: wire.Context, msg: ChangePin) -> Awaitable[None]: diff --git a/core/src/apps/ur_registry/chains/bitcoin/transaction.py b/core/src/apps/ur_registry/chains/bitcoin/transaction.py index 734474ebdf..83a47c3174 100644 --- a/core/src/apps/ur_registry/chains/bitcoin/transaction.py +++ b/core/src/apps/ur_registry/chains/bitcoin/transaction.py @@ -355,14 +355,9 @@ async def run(self): found = True our_keys += 1 else: - if __debug__: - print( - f"Key fingerprint {keypath.fingerprint} does not match master key {master_fp}" - ) - else: - raise MismatchError( - "Key fingerprint does not match master key" - ) + raise MismatchError( + "Key fingerprint does not match master key" + ) elif txinputtype.script_type in SCHNORR_SCRIPT_TYPES: for key, (_, origin) in psbt_in.tap_bip32_paths.items(): # Assume key path signing @@ -378,14 +373,9 @@ async def run(self): our_keys += 1 break else: - if __debug__: - print( - f"Key fingerprint {origin.fingerprint} does not match master key {master_fp}" - ) - else: - raise MismatchError( - "Key fingerprint does not match master key" - ) + raise MismatchError( + "Key fingerprint does not match master key" + ) # Determine if we need to do more passes to sign everything if our_keys > passes: @@ -434,14 +424,9 @@ async def run(self): if not wit or (wit and ver == 0): for _, keypath in psbt_out.hd_keypaths.items(): if keypath.fingerprint != master_fp: - if __debug__: - print( - f"Key fingerprint {keypath.fingerprint} does not match master key {master_fp}" - ) - else: - raise MismatchError( - "Key fingerprint does not match master key" - ) + raise MismatchError( + "Key fingerprint does not match master key" + ) wit, ver, prog = out.is_witness() if out.is_p2pkh(): txoutput.address_n = keypath.path diff --git a/core/src/apps/ur_registry/chains/ethereum/eth_sign_request.py b/core/src/apps/ur_registry/chains/ethereum/eth_sign_request.py index f06e53a1e6..18daef8443 100644 --- a/core/src/apps/ur_registry/chains/ethereum/eth_sign_request.py +++ b/core/src/apps/ur_registry/chains/ethereum/eth_sign_request.py @@ -214,14 +214,9 @@ async def common_check(self): # pyright: on expected_fingerprint = key_path.source_fingerprint if resp.root_fingerprint != expected_fingerprint: - if __debug__: - print( - f"Fingerprint mismatch: got {resp.root_fingerprint} expected {expected_fingerprint}" - ) - else: - raise MismatchError( - f"Fingerprint mismatch: got {resp.root_fingerprint} expected {expected_fingerprint}" - ) + raise MismatchError( + f"Fingerprint mismatch: got {resp.root_fingerprint} expected {expected_fingerprint}" + ) @staticmethod async def gen_request(ur): diff --git a/core/src/apps/ur_registry/chains/hardware_requests/hardware_call.py b/core/src/apps/ur_registry/chains/hardware_requests/hardware_call.py index 3e68903c96..963f896151 100644 --- a/core/src/apps/ur_registry/chains/hardware_requests/hardware_call.py +++ b/core/src/apps/ur_registry/chains/hardware_requests/hardware_call.py @@ -75,12 +75,9 @@ async def common_check(self): assert resp.root_fingerprint is not None, "Root fingerprint should not be None" xfp = hexlify(int.to_bytes(resp.root_fingerprint, 4, "big")).decode() if xfp != expected_fingerprint: - if __debug__: - print(f"Fingerprint mismatch: {xfp} != {expected_fingerprint}") - else: - raise MismatchError( - f"Fingerprint mismatch: got {resp.root_fingerprint} expected {expected_fingerprint}" - ) + raise MismatchError( + f"Fingerprint mismatch: got {resp.root_fingerprint} expected {expected_fingerprint}" + ) @staticmethod async def gen_request(ur): diff --git a/core/src/apps/ur_registry/chains/solana/sol_sign_request.py b/core/src/apps/ur_registry/chains/solana/sol_sign_request.py index 4da50a0abd..ab7d0071e5 100644 --- a/core/src/apps/ur_registry/chains/solana/sol_sign_request.py +++ b/core/src/apps/ur_registry/chains/solana/sol_sign_request.py @@ -198,14 +198,9 @@ async def common_check(self): # pyright: on expected_fingerprint = key_path.source_fingerprint if resp.root_fingerprint != expected_fingerprint: - if __debug__: - print( - f"Fingerprint mismatch: got {resp.root_fingerprint} expected {expected_fingerprint}" - ) - else: - raise MismatchError( - f"Fingerprint mismatch: got {resp.root_fingerprint} expected {expected_fingerprint}" - ) + raise MismatchError( + f"Fingerprint mismatch: got {resp.root_fingerprint} expected {expected_fingerprint}" + ) @staticmethod async def gen_request(ur): diff --git a/core/src/storage/cache.py b/core/src/storage/cache.py index 16f32d1ac9..3603e36d13 100644 --- a/core/src/storage/cache.py +++ b/core/src/storage/cache.py @@ -33,6 +33,7 @@ APP_COMMON_REQUEST_PIN_LAST_UNLOCK = 3 | _SESSIONLESS_FLAG APP_COMMON_BUSY_DEADLINE_MS = 4 | _SESSIONLESS_FLAG APP_COMMON_CLIENT_CONTAINS_ATTACH = 5 | _SESSIONLESS_FLAG +APP_COMMON_PASSPHRASE_PIN_ENABLED = 6 | _SESSIONLESS_FLAG SESSION_DIRIVE_CARDANO = False @@ -144,6 +145,7 @@ def __init__(self) -> None: 8, # APP_COMMON_REQUEST_PIN_LAST_UNLOCK 8, # APP_COMMON_BUSY_DEADLINE_MS 1, # APP_COMMON_CLIENT_CONTAINS_ATTACH + 1, # APP_COMMON_PASSPHRASE_PIN_ENABLED ) super().__init__() diff --git a/core/src/storage/device.py b/core/src/storage/device.py index 6a5219ac50..c522709e71 100644 --- a/core/src/storage/device.py +++ b/core/src/storage/device.py @@ -29,7 +29,6 @@ _LANGUAGE_VALUE: str | None = None _LABEL_VALUE: str | None = None _USE_PASSPHRASE_VALUE: bool | None = None -_USE_PASSPHRASE_PIN_VALUE: bool | None = None _AUTO_PASSPHRASE_VALUE: bool | None = None _PASSPHRASE_ALWAYS_ON_DEVICE_VALUE: bool | None = None _AUTOLOCK_DELAY_MS_VALUE: int | None = None @@ -1426,10 +1425,10 @@ def is_passphrase_pin_enabled() -> bool: Returns True if the device is currently in passphrase pin mode. In this mode, a separate PIN is used to access the passphrase. """ - global _USE_PASSPHRASE_PIN_VALUE - if _USE_PASSPHRASE_PIN_VALUE is None: - _USE_PASSPHRASE_PIN_VALUE = common.get_bool(_NAMESPACE, _USE_PASSPHRASE_PIN) - return _USE_PASSPHRASE_PIN_VALUE + cached = storage.cache.get(storage.cache.APP_COMMON_PASSPHRASE_PIN_ENABLED) + if cached is None: + return False + return cached == b"\x01" def set_passphrase_pin_enabled(enable: bool) -> None: @@ -1439,15 +1438,14 @@ def set_passphrase_pin_enabled(enable: bool) -> None: Note: This requires passphrase to be enabled first. """ - global _USE_PASSPHRASE_PIN_VALUE if enable and not is_passphrase_enabled(): raise ValueError( "Cannot enable passphrase PIN without enabling passphrase first" ) - common.set_bool(_NAMESPACE, _USE_PASSPHRASE_PIN, enable) - _USE_PASSPHRASE_PIN_VALUE = enable + cached_bytes = b"\x01" if enable else b"\x00" + storage.cache.set(storage.cache.APP_COMMON_PASSPHRASE_PIN_ENABLED, cached_bytes) def is_passphrase_auto_status() -> bool: @@ -1482,7 +1480,6 @@ def clear_global_cache() -> None: global _LABEL_VALUE global _USE_PASSPHRASE_VALUE global _AUTO_PASSPHRASE_VALUE - global _USE_PASSPHRASE_PIN_VALUE global _PASSPHRASE_ALWAYS_ON_DEVICE_VALUE global _AUTOLOCK_DELAY_MS_VALUE global _HOMESCREEN_VALUE @@ -1522,7 +1519,6 @@ def clear_global_cache() -> None: _LABEL_VALUE = None _USE_PASSPHRASE_VALUE = None _AUTO_PASSPHRASE_VALUE = None - _USE_PASSPHRASE_PIN_VALUE = None _PASSPHRASE_ALWAYS_ON_DEVICE_VALUE = None _AUTOLOCK_DELAY_MS_VALUE = None _HOMESCREEN_VALUE = None diff --git a/core/src/trezor/lvglui/i18n/keys.py b/core/src/trezor/lvglui/i18n/keys.py index fba863ced2..083cd17e01 100644 --- a/core/src/trezor/lvglui/i18n/keys.py +++ b/core/src/trezor/lvglui/i18n/keys.py @@ -1127,6 +1127,7 @@ LIST_KEY__CHAIN_NAME__COLON = 509 # Account LIST_KEY__ACCOUNT__COLON = 510 +FIELDS_ACCOUNT = 510 # Sequence LIST_KEY__SEQUENCE__COLON = 511 # Delegator @@ -2015,7 +2016,7 @@ # Passphrase set and attached to PIN PASSPHRASE__SET = 918 # This PIN unlocks only the hidden wallet. For any security-related operation, -# you’ll need the PIN of the standard wallet. +# you'll need the PIN of the standard wallet. PASSPHRASE__SET_DESC = 919 # Fingerprint data is protected by security chips. CONTENT__FINGERPRINT_DATA_IS_PROTECTED_BY_SECURITY_CHIPS = 920 @@ -2238,4 +2239,30 @@ SUBTITLE__THIS_IS_SHARE_STR_OF_STR = 1017 # Threshold of this group has been reached. Input share from different group. SUBTITLE__ENTER_A_DIFFERENT_SHARE = 1018 +# This PIN has already been used. Overwriting it will remove the previously se +# t Passphrase. Do you want to overwrite it? +TITLE__PIN_ALREADY_USED_DESC = 1019 +# 7702 Upgrade +TITLE_UPGRADE_SMART_ACCOUNT = 1020 +# You are upgrading this account to {platform} smart account. Sign only if you +# understand the risks. +BANNER_UPGRADING_SMART_ACCOUNT_WARNING = 1021 +# Delegate to +FIELDS_DELEGATE_TO = 1022 +# Delegate on Network +FIELDS_DELEGATE_ON_NETWORK = 1023 +# Revoke 7702 Delegation +TITLE_REVOKE_SMART_ACCOUNT_DELEGATION = 1024 +# You are revoking the EIP-7702 delegation. Smart account features will be dis +# abled. +BANNER_REVOKE_SMART_ACCOUNT_WARNING = 1025 +# Delegation Blocked +TITLE_SMART_ACCOUNT_DELEGATION_BLOCKED = 1026 +# This authorization delegates authority to a smart contract not included on t +# he whitelist. +BANNER_NOT_IN_SMART_ACCOUNT_WHITELIST = 1027 +# Revoke on Network +FIELDS_REVOKE_ON_NETWORK = 1028 +# Understand +BUTTON_UNDERSTAND = 1029 # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/de.py b/core/src/trezor/lvglui/i18n/locales/de.py index ef5ae03db9..f7625c075f 100644 --- a/core/src/trezor/lvglui/i18n/locales/de.py +++ b/core/src/trezor/lvglui/i18n/locales/de.py @@ -1019,5 +1019,16 @@ "Wiederherstellungsphrase-Erstellung abbrechen?", "Dies ist Anteil {num1} von {num2}.", "Der Schwellenwert dieser Gruppe wurde erreicht. Bitte einen Anteil aus einer anderen Gruppe eingeben.", + "Dieser PIN wurde bereits verwendet. Wenn Sie ihn überschreiben, wird die zuvor festgelegte Passphrase entfernt. Möchten Sie ihn überschreiben?", + "7702-Upgrade", + "Sie aktualisieren dieses Konto zu einem {platform} Smart Account. Unterschreiben Sie nur, wenn Sie die Risiken verstehen.", + "Delegieren an", + "Im Netzwerk delegieren", + "7702-Delegation widerrufen", + "Sie widerrufen die EIP-7702-Delegation. Die Funktionen des Smart Accounts werden deaktiviert.", + "Delegierung blockiert", + "Diese Autorisierung überträgt die Befugnis an einen Smart Contract, der nicht auf der Whitelist steht.", + "Im Netzwerk widerrufen", + "Verstanden", ] # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/en.py b/core/src/trezor/lvglui/i18n/locales/en.py index 5cf9d2b16d..54a90899e6 100644 --- a/core/src/trezor/lvglui/i18n/locales/en.py +++ b/core/src/trezor/lvglui/i18n/locales/en.py @@ -919,7 +919,7 @@ "Forget your Passphrase will lose access to funds linked to your hidden wallet.", "I undersand", "Passphrase set and attached to PIN", - "This PIN unlocks only the hidden wallet. For any security-related operation, you’ll need the PIN of the standard wallet.", + "This PIN unlocks only the hidden wallet. For any security-related operation, you'll need the PIN of the standard wallet.", "Fingerprint data is protected by security chips.", "Once removed, you won’t be able to unlock the device with this PIN.", "PIN Removed", @@ -1019,5 +1019,16 @@ "Abort Recovery Phrase Creation?", "This is Share {num1} of {num2}.", "Threshold of this group has been reached. Input share from different group.", + "This PIN has already been used. Overwriting it will remove the previously set Passphrase. Do you want to overwrite it?", + "7702 Upgrade", + "You are upgrading this account to {platform} smart account. Sign only if you understand the risks.", + "Delegate to", + "Delegate on Network", + "Revoke 7702 Delegation", + "You are revoking the EIP-7702 delegation. Smart account features will be disabled.", + "Delegation Blocked", + "This authorization delegates authority to a smart contract not included on the whitelist.", + "Revoke on Network", + "Understand", ] # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/es.py b/core/src/trezor/lvglui/i18n/locales/es.py index 608bf84c28..ebe3b1f72b 100644 --- a/core/src/trezor/lvglui/i18n/locales/es.py +++ b/core/src/trezor/lvglui/i18n/locales/es.py @@ -1019,5 +1019,16 @@ "¿Abortar la creación de la frase de recuperación?", "Esta es la parte {num1} de {num2}.", "Se ha alcanzado el umbral de este grupo. Introduzca una participación de un grupo diferente.", + "Este PIN ya ha sido utilizado. Si lo sobrescribes, se eliminará la frase de contraseña establecida anteriormente. ¿Deseas sobrescribirlo?", + "Actualización 7702", + "Estás actualizando esta cuenta a una cuenta inteligente de {platform}. Firma solo si comprendes los riesgos.", + "Delegar a", + "Delegar en la red", + "Revocar delegación 7702", + "Está revocando la delegación EIP-7702. Las funciones de la cuenta inteligente se desactivarán.", + "Delegación bloqueada", + "Esta autorización delega autoridad a un contrato inteligente que no está incluido en la lista blanca.", + "Revocar en la red", + "Entender", ] # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/fr.py b/core/src/trezor/lvglui/i18n/locales/fr.py index db514c84a4..93d7ef3883 100644 --- a/core/src/trezor/lvglui/i18n/locales/fr.py +++ b/core/src/trezor/lvglui/i18n/locales/fr.py @@ -1019,5 +1019,16 @@ "Abandonner la création de la phrase de récupération ?", "Ceci est la part {num1} sur {num2}.", "Le seuil de ce groupe a été atteint. Veuillez saisir une part d'un groupe différent.", + "Ce code PIN est déjà utilisé. Le remplacer supprimera la phrase secrète précédemment définie. Voulez-vous le remplacer ?", + "Mise à niveau 7702", + "Vous mettez à niveau ce compte vers un compte intelligent {platform}. Ne signez que si vous comprenez les risques.", + "Déléguer à", + "Déléguer sur le réseau", + "Révoquer la délégation 7702", + "Vous révoquez la délégation EIP-7702. Les fonctionnalités de compte intelligent seront désactivées.", + "Délégation bloquée", + "Cette autorisation délègue l'autorité à un contrat intelligent non inclus dans la liste blanche.", + "Révoquer sur le réseau", + "Comprendre", ] # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/it.py b/core/src/trezor/lvglui/i18n/locales/it.py index 258b699fd9..3454cacccd 100644 --- a/core/src/trezor/lvglui/i18n/locales/it.py +++ b/core/src/trezor/lvglui/i18n/locales/it.py @@ -1019,5 +1019,16 @@ "Annullare la creazione della frase di recupero?", "Questa è la quota {num1} di {num2}.", "La soglia di questo gruppo è stata raggiunta. Inserisci una quota da un gruppo diverso.", + "Questo PIN è già stato utilizzato. Sovrascrivendolo verrà rimossa la Passphrase precedentemente impostata. Vuoi sovrascriverlo?", + "Aggiornamento 7702", + "Stai aggiornando questo account a un account smart {platform}. Firma solo se comprendi i rischi.", + "Delegare a", + "Delega sulla rete", + "Revoca delega 7702", + "Stai revocando la delega EIP-7702. Le funzionalità dell'account smart verranno disabilitate.", + "Delegazione bloccata", + "Questa autorizzazione delega l'autorità a uno smart contract non incluso nella whitelist.", + "Revoca sulla rete", + "Capisco", ] # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/ja.py b/core/src/trezor/lvglui/i18n/locales/ja.py index a470c3a2a4..990b760f16 100644 --- a/core/src/trezor/lvglui/i18n/locales/ja.py +++ b/core/src/trezor/lvglui/i18n/locales/ja.py @@ -1019,5 +1019,16 @@ "リカバリーフレーズの作成を中止しますか?", "これは {num2} のうちの {num1} つ目の共有です。", "このグループのしきい値に達しました。別のグループからシェアを入力してください。", + "このPINはすでに使用されています。上書きすると、以前に設定したパスフレーズが削除されます。上書きしてもよろしいですか?", + "7702 アップグレード", + "このアカウントを{platform}スマートアカウントにアップグレードしようとしています。リスクを理解している場合のみ署名してください。", + "委任先", + "ネットワークで委任", + "7702の委任を取り消す", + "EIP-7702の委任を取り消します。スマートアカウントの機能が無効になります。", + "委任がブロックされました", + "この認証は、ホワイトリストに含まれていないスマートコントラクトに権限を委譲します。", + "ネットワーク上で取り消す", + "理解しました", ] # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/ko.py b/core/src/trezor/lvglui/i18n/locales/ko.py index 1dfc71f197..d855c990c2 100644 --- a/core/src/trezor/lvglui/i18n/locales/ko.py +++ b/core/src/trezor/lvglui/i18n/locales/ko.py @@ -1019,5 +1019,16 @@ "복구 구문 생성을 중단하시겠습니까?", "이것은 {num2} 중 {num1}번째 공유입니다.", "이 그룹의 임계값에 도달했습니다. 다른 그룹의 입력 쉐어를 사용하세요.", + "이 PIN은 이미 사용되었습니다. 덮어쓰면 이전에 설정된 암호가 삭제됩니다. 덮어쓰시겠습니까?", + "7702 업그레이드", + "이 계정을 {platform} 스마트 계정으로 업그레이드하고 있습니다. 위험을 이해하는 경우에만 서명하세요.", + "위임 대상", + "네트워크에서 위임", + "7702 위임 해제", + "EIP-7702 위임을 해제하고 있습니다. 스마트 계정 기능이 비활성화됩니다.", + "위임 차단됨", + "이 권한 부여는 화이트리스트에 포함되지 않은 스마트 계약에 권한을 위임합니다.", + "네트워크에서 취소", + "이해하다", ] # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/pt_br.py b/core/src/trezor/lvglui/i18n/locales/pt_br.py index 4f301408ae..8423443458 100644 --- a/core/src/trezor/lvglui/i18n/locales/pt_br.py +++ b/core/src/trezor/lvglui/i18n/locales/pt_br.py @@ -1019,5 +1019,16 @@ "Cancelar a criação da frase de recuperação?", "Esta é a Ação {num1} de {num2}.", "O limite deste grupo foi atingido. Insira uma parte de um grupo diferente.", + "Este PIN já foi usado. Sobrescrevê-lo removerá a Passphrase definida anteriormente. Deseja sobrescrevê-lo?", + "7702 Atualização", + "Você está atualizando esta conta para uma conta inteligente {platform}. Assine apenas se você entender os riscos.", + "Delegar para", + "Delegar na rede", + "Revogar Delegação 7702", + "Você está revogando a delegação EIP-7702. Os recursos de conta inteligente serão desativados.", + "Delegação Bloqueada", + "Esta autorização delega autoridade a um contrato inteligente não incluído na lista de permissões.", + "Revogar na rede", + "Entender", ] # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/ru.py b/core/src/trezor/lvglui/i18n/locales/ru.py index abcfca6e6d..18f98ca572 100644 --- a/core/src/trezor/lvglui/i18n/locales/ru.py +++ b/core/src/trezor/lvglui/i18n/locales/ru.py @@ -1019,5 +1019,16 @@ "Прервать создание фразы восстановления?", "Это доля {num1} из {num2}.", "Порог этой группы достигнут. Введите долю из другой группы.", + "Этот PIN уже был использован. Если вы перезапишете его, ранее установленная парольная фраза будет удалена. Вы хотите перезаписать его?", + "Обновление 7702", + "Вы обновляете эту учетную запись до смарт-аккаунта {platform}. Подписывайте только если понимаете риски.", + "Делегировать кому", + "Делегировать в сети", + "Отозвать делегирование 7702", + "Вы отзываете делегацию EIP-7702. Функции смарт-аккаунта будут отключены.", + "Делегация заблокирована", + "Эта авторизация делегирует полномочия смарт-контракту, который не включён в белый список.", + "Отозвать в сети", + "Понять", ] # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/zh_cn.py b/core/src/trezor/lvglui/i18n/locales/zh_cn.py index 53b0f9830b..91a8089ab4 100644 --- a/core/src/trezor/lvglui/i18n/locales/zh_cn.py +++ b/core/src/trezor/lvglui/i18n/locales/zh_cn.py @@ -1019,5 +1019,16 @@ "终止创建助记词?", "这是第 {num1} 份,共 {num2} 份。", "该组已达最低阈值条件,请输入其他组的分片。", + "此 PIN 码已被使用。覆盖它将会移除先前设置的 Passphrase。您确定要覆盖它吗?", + "7702 升级", + "您正在将此账户升级为 {platform} 智能账户。仅在您了解风险的情况下才签署。", + "委托给", + "委托的链", + "撤销 7702 委托", + "您正在撤销 EIP-7702 委托。智能账户功能将被禁用。", + "委托已拦截", + "此授权将权限委托给未包含在白名单中的智能合约。", + "撤销授权的链", + "明白", ] # fmt: on diff --git a/core/src/trezor/lvglui/i18n/locales/zh_hk.py b/core/src/trezor/lvglui/i18n/locales/zh_hk.py index 364cf6dbf2..ed29556fc0 100644 --- a/core/src/trezor/lvglui/i18n/locales/zh_hk.py +++ b/core/src/trezor/lvglui/i18n/locales/zh_hk.py @@ -1014,10 +1014,21 @@ "交易哈希", "此代幣未被硬件錢包識別。請仔細驗證。", "收款地址是已知的能源租賃服務提供商。", - "請配合最新版本 OneKey App 使用「綁定 PIN 碼」功能。", + "請配合最新版 OneKey App 使用「Passphrase 綁定 PIN 碼」功能。", "確認請求", "終止創建助記詞?", "這是第 {num1} 份,共 {num2} 份。", "該組已達最低閾值條件,請輸入其他組的分片。", + "此 PIN 碼已被使用。覆寫它將會移除先前設定的 Passphrase。您確定要覆寫嗎?", + "7702 升級", + "您正在將此帳戶升級為 {platform} 智能帳戶。只有在您了解風險的情況下才簽署。", + "委託給", + "委托的链", + "撤銷 7702 委托", + "您正在撤銷 EIP-7702 委託。智能賬戶功能將被停用。", + "委托已被阻止", + "此授權將權限委託給一個不在白名單上的智能合約。", + "撤銷授權的链", + "明白", ] # fmt: on diff --git a/core/src/trezor/lvglui/scrs/components/keyboard.py b/core/src/trezor/lvglui/scrs/components/keyboard.py index a0132b29f3..be54971e8c 100644 --- a/core/src/trezor/lvglui/scrs/components/keyboard.py +++ b/core/src/trezor/lvglui/scrs/components/keyboard.py @@ -552,7 +552,7 @@ def toggle_number_input_keys(self, enable: bool): if enable: self.dummy_ctl_map = [] self.dummy_ctl_map.extend(self.ctrl_map) - if self.input_len > 3: + if self.input_len >= self.min_len: self.dummy_ctl_map[-1] &= ( self.dummy_ctl_map[-1] ^ lv.btnmatrix.CTRL.DISABLED ) diff --git a/core/src/trezor/lvglui/scrs/homescreen.py b/core/src/trezor/lvglui/scrs/homescreen.py index 091b711576..c15acb1d34 100644 --- a/core/src/trezor/lvglui/scrs/homescreen.py +++ b/core/src/trezor/lvglui/scrs/homescreen.py @@ -4315,8 +4315,7 @@ def eventhandler(self, event_obj): allow_cancel=False, callback=self.back, allow_fingerprint=False, - pin_use_type=1, - standy_wall_only=True, + pin_use_type=2, ) ) else: @@ -4556,8 +4555,6 @@ def __init__(self, prev_scr=None): self._init = True else: utils.mark_collecting_fingerprint_done() - if not self.is_visible(): - self.load_screen(self) return super().__init__(prev_scr, title=_(i18n_keys.TITLE__SECURITY), nav_back=True) diff --git a/core/src/trezor/lvglui/scrs/lockscreen.py b/core/src/trezor/lvglui/scrs/lockscreen.py index bb2be8538b..d561dea7c8 100644 --- a/core/src/trezor/lvglui/scrs/lockscreen.py +++ b/core/src/trezor/lvglui/scrs/lockscreen.py @@ -206,9 +206,6 @@ def on_slide_up(self, event_obj: lv.event_t): from apps.base import unlock_device workflow.spawn(unlock_device()) - import storage.cache - - storage.cache.start_session() def _load_scr(self, scr: "Screen", back: bool = False) -> None: lv.scr_load(scr) diff --git a/core/src/trezor/lvglui/scrs/pinscreen.py b/core/src/trezor/lvglui/scrs/pinscreen.py index 5be280a2e8..5142151776 100644 --- a/core/src/trezor/lvglui/scrs/pinscreen.py +++ b/core/src/trezor/lvglui/scrs/pinscreen.py @@ -553,6 +553,20 @@ async def passphrase_pin_mismatch(ctx) -> None: ) +async def request_change_passphrase_pin(ctx) -> str: + while True: + pin1 = await request_passphrase_pin(ctx, _(i18n_keys.TITLE__ENTER_NEW_PIN)) + if pin1 == 0: + return pin1 + + pin2 = await request_passphrase_pin(ctx, _(i18n_keys.TITLE__ENTER_PIN_AGAIN)) + if pin2 == 0: + return pin2 + if pin1 == pin2: + return pin1 + await passphrase_pin_mismatch(ctx) + + class InputMainPin(FullSizeWindow): def __init__(self): super().__init__( diff --git a/core/src/trezor/uart.py b/core/src/trezor/uart.py index d2d86b1331..4fc580eaaf 100644 --- a/core/src/trezor/uart.py +++ b/core/src/trezor/uart.py @@ -149,6 +149,8 @@ async def handle_fingerprint(): if __debug__: print(f"fingerprint match {match_id}") # motor.vibrate(motor.SUCCESS) + if device.is_passphrase_pin_enabled(): + device.set_passphrase_pin_enabled(False) # # 1. publish signal if fingerprints.has_takers(): if __debug__: @@ -160,7 +162,6 @@ async def handle_fingerprint(): if __debug__: print(f"fingerprint unlock result {res}") await base.unlock_device() - # await loop.sleep(2000) return else: