mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-05-29 04:08:46 +00:00
feat(core): Support 50 digit PIN and wipe code.
This commit is contained in:
parent
c68e91c12a
commit
3084d1196d
@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
- Allow decreasing the output value in RBF transactions. [#1491]
|
- Allow decreasing the output value in RBF transactions. [#1491]
|
||||||
- Cardano: Allow stake pool registrations with zero margin. [#1502]
|
- Cardano: Allow stake pool registrations with zero margin. [#1502]
|
||||||
- Cardano: Assets are now shown as CIP-0014. [#1510]
|
- Cardano: Assets are now shown as CIP-0014. [#1510]
|
||||||
|
- Support PIN of unlimited length. [#1167]
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
@ -358,6 +359,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
[#1139]: https://github.com/trezor/trezor-firmware/issues/1139
|
[#1139]: https://github.com/trezor/trezor-firmware/issues/1139
|
||||||
[#1159]: https://github.com/trezor/trezor-firmware/issues/1159
|
[#1159]: https://github.com/trezor/trezor-firmware/issues/1159
|
||||||
[#1165]: https://github.com/trezor/trezor-firmware/pull/1165
|
[#1165]: https://github.com/trezor/trezor-firmware/pull/1165
|
||||||
|
[#1167]: https://github.com/trezor/trezor-firmware/issues/1167
|
||||||
[#1173]: https://github.com/trezor/trezor-firmware/pull/1173
|
[#1173]: https://github.com/trezor/trezor-firmware/pull/1173
|
||||||
[#1184]: https://github.com/trezor/trezor-firmware/issues/1184
|
[#1184]: https://github.com/trezor/trezor-firmware/issues/1184
|
||||||
[#1188]: https://github.com/trezor/trezor-firmware/issues/1188
|
[#1188]: https://github.com/trezor/trezor-firmware/issues/1188
|
||||||
|
@ -66,13 +66,15 @@ STATIC mp_obj_t mod_trezorconfig_init(size_t n_args, const mp_obj_t *args) {
|
|||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_init_obj, 0, 1,
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_init_obj, 0, 1,
|
||||||
mod_trezorconfig_init);
|
mod_trezorconfig_init);
|
||||||
|
|
||||||
/// def unlock(pin: int, ext_salt: Optional[bytes]) -> bool:
|
/// def unlock(pin: str, ext_salt: Optional[bytes]) -> bool:
|
||||||
/// """
|
/// """
|
||||||
/// Attempts to unlock the storage with the given PIN and external salt.
|
/// Attempts to unlock the storage with the given PIN and external salt.
|
||||||
/// Returns True on success, False on failure.
|
/// Returns True on success, False on failure.
|
||||||
/// """
|
/// """
|
||||||
STATIC mp_obj_t mod_trezorconfig_unlock(mp_obj_t pin, mp_obj_t ext_salt) {
|
STATIC mp_obj_t mod_trezorconfig_unlock(mp_obj_t pin, mp_obj_t ext_salt) {
|
||||||
uint32_t pin_i = trezor_obj_get_uint(pin);
|
mp_buffer_info_t pin_b = {0};
|
||||||
|
mp_get_buffer_raise(pin, &pin_b, MP_BUFFER_READ);
|
||||||
|
|
||||||
mp_buffer_info_t ext_salt_b = {0};
|
mp_buffer_info_t ext_salt_b = {0};
|
||||||
ext_salt_b.buf = NULL;
|
ext_salt_b.buf = NULL;
|
||||||
if (ext_salt != mp_const_none) {
|
if (ext_salt != mp_const_none) {
|
||||||
@ -81,7 +83,7 @@ STATIC mp_obj_t mod_trezorconfig_unlock(mp_obj_t pin, mp_obj_t ext_salt) {
|
|||||||
mp_raise_msg(&mp_type_ValueError, "Invalid length of external salt.");
|
mp_raise_msg(&mp_type_ValueError, "Invalid length of external salt.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sectrue != storage_unlock(pin_i, ext_salt_b.buf)) {
|
if (sectrue != storage_unlock(pin_b.buf, pin_b.len, ext_salt_b.buf)) {
|
||||||
return mp_const_false;
|
return mp_const_false;
|
||||||
}
|
}
|
||||||
return mp_const_true;
|
return mp_const_true;
|
||||||
@ -89,7 +91,7 @@ STATIC mp_obj_t mod_trezorconfig_unlock(mp_obj_t pin, mp_obj_t ext_salt) {
|
|||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorconfig_unlock_obj,
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorconfig_unlock_obj,
|
||||||
mod_trezorconfig_unlock);
|
mod_trezorconfig_unlock);
|
||||||
|
|
||||||
/// def check_pin(pin: int, ext_salt: Optional[bytes]) -> bool:
|
/// def check_pin(pin: str, ext_salt: Optional[bytes]) -> bool:
|
||||||
/// """
|
/// """
|
||||||
/// Check the given PIN with the given external salt.
|
/// Check the given PIN with the given external salt.
|
||||||
/// Returns True on success, False on failure.
|
/// Returns True on success, False on failure.
|
||||||
@ -148,8 +150,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_get_pin_rem_obj,
|
|||||||
mod_trezorconfig_get_pin_rem);
|
mod_trezorconfig_get_pin_rem);
|
||||||
|
|
||||||
/// def change_pin(
|
/// def change_pin(
|
||||||
/// oldpin: int,
|
/// oldpin: str,
|
||||||
/// newpin: int,
|
/// newpin: str,
|
||||||
/// old_ext_salt: Optional[bytes],
|
/// old_ext_salt: Optional[bytes],
|
||||||
/// new_ext_salt: Optional[bytes],
|
/// new_ext_salt: Optional[bytes],
|
||||||
/// ) -> bool:
|
/// ) -> bool:
|
||||||
@ -158,8 +160,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_get_pin_rem_obj,
|
|||||||
/// """
|
/// """
|
||||||
STATIC mp_obj_t mod_trezorconfig_change_pin(size_t n_args,
|
STATIC mp_obj_t mod_trezorconfig_change_pin(size_t n_args,
|
||||||
const mp_obj_t *args) {
|
const mp_obj_t *args) {
|
||||||
uint32_t oldpin = trezor_obj_get_uint(args[0]);
|
mp_buffer_info_t oldpin = {0};
|
||||||
uint32_t newpin = trezor_obj_get_uint(args[1]);
|
mp_get_buffer_raise(args[0], &oldpin, MP_BUFFER_READ);
|
||||||
|
|
||||||
|
mp_buffer_info_t newpin = {0};
|
||||||
|
mp_get_buffer_raise(args[1], &newpin, MP_BUFFER_READ);
|
||||||
|
|
||||||
mp_buffer_info_t ext_salt_b = {0};
|
mp_buffer_info_t ext_salt_b = {0};
|
||||||
const uint8_t *old_ext_salt = NULL;
|
const uint8_t *old_ext_salt = NULL;
|
||||||
if (args[2] != mp_const_none) {
|
if (args[2] != mp_const_none) {
|
||||||
@ -176,8 +182,8 @@ STATIC mp_obj_t mod_trezorconfig_change_pin(size_t n_args,
|
|||||||
new_ext_salt = ext_salt_b.buf;
|
new_ext_salt = ext_salt_b.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sectrue !=
|
if (sectrue != storage_change_pin(oldpin.buf, oldpin.len, newpin.buf,
|
||||||
storage_change_pin(oldpin, newpin, old_ext_salt, new_ext_salt)) {
|
newpin.len, old_ext_salt, new_ext_salt)) {
|
||||||
return mp_const_false;
|
return mp_const_false;
|
||||||
}
|
}
|
||||||
return mp_const_true;
|
return mp_const_true;
|
||||||
@ -185,13 +191,14 @@ STATIC mp_obj_t mod_trezorconfig_change_pin(size_t n_args,
|
|||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_change_pin_obj, 4,
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_change_pin_obj, 4,
|
||||||
4, mod_trezorconfig_change_pin);
|
4, mod_trezorconfig_change_pin);
|
||||||
|
|
||||||
/// def ensure_not_wipe_code(pin: int) -> None:
|
/// def ensure_not_wipe_code(pin: str) -> None:
|
||||||
/// """
|
/// """
|
||||||
/// Wipes the device if the entered PIN is the wipe code.
|
/// Wipes the device if the entered PIN is the wipe code.
|
||||||
/// """
|
/// """
|
||||||
STATIC mp_obj_t mod_trezorconfig_ensure_not_wipe_code(mp_obj_t pin) {
|
STATIC mp_obj_t mod_trezorconfig_ensure_not_wipe_code(mp_obj_t pin) {
|
||||||
uint32_t pin_i = trezor_obj_get_uint(pin);
|
mp_buffer_info_t pin_b = {0};
|
||||||
storage_ensure_not_wipe_code(pin_i);
|
mp_get_buffer_raise(pin, &pin_b, MP_BUFFER_READ);
|
||||||
|
storage_ensure_not_wipe_code(pin_b.buf, pin_b.len);
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorconfig_ensure_not_wipe_code_obj,
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorconfig_ensure_not_wipe_code_obj,
|
||||||
@ -211,17 +218,21 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_has_wipe_code_obj,
|
|||||||
mod_trezorconfig_has_wipe_code);
|
mod_trezorconfig_has_wipe_code);
|
||||||
|
|
||||||
/// def change_wipe_code(
|
/// def change_wipe_code(
|
||||||
/// pin: int,
|
/// pin: str,
|
||||||
/// ext_salt: Optional[bytes],
|
/// ext_salt: Optional[bytes],
|
||||||
/// wipe_code: int,
|
/// wipe_code: str,
|
||||||
/// ) -> bool:
|
/// ) -> bool:
|
||||||
/// """
|
/// """
|
||||||
/// Change wipe code. Returns True on success, False on failure.
|
/// Change wipe code. Returns True on success, False on failure.
|
||||||
/// """
|
/// """
|
||||||
STATIC mp_obj_t mod_trezorconfig_change_wipe_code(size_t n_args,
|
STATIC mp_obj_t mod_trezorconfig_change_wipe_code(size_t n_args,
|
||||||
const mp_obj_t *args) {
|
const mp_obj_t *args) {
|
||||||
uint32_t pin = trezor_obj_get_uint(args[0]);
|
mp_buffer_info_t pin_b = {0};
|
||||||
uint32_t wipe_code = trezor_obj_get_uint(args[2]);
|
mp_get_buffer_raise(args[0], &pin_b, MP_BUFFER_READ);
|
||||||
|
|
||||||
|
mp_buffer_info_t wipe_code_b = {0};
|
||||||
|
mp_get_buffer_raise(args[2], &wipe_code_b, MP_BUFFER_READ);
|
||||||
|
|
||||||
mp_buffer_info_t ext_salt_b = {0};
|
mp_buffer_info_t ext_salt_b = {0};
|
||||||
const uint8_t *ext_salt = NULL;
|
const uint8_t *ext_salt = NULL;
|
||||||
if (args[1] != mp_const_none) {
|
if (args[1] != mp_const_none) {
|
||||||
@ -231,7 +242,8 @@ STATIC mp_obj_t mod_trezorconfig_change_wipe_code(size_t n_args,
|
|||||||
ext_salt = ext_salt_b.buf;
|
ext_salt = ext_salt_b.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sectrue != storage_change_wipe_code(pin, ext_salt, wipe_code)) {
|
if (sectrue != storage_change_wipe_code(pin_b.buf, pin_b.len, ext_salt,
|
||||||
|
wipe_code_b.buf, wipe_code_b.len)) {
|
||||||
return mp_const_false;
|
return mp_const_false;
|
||||||
}
|
}
|
||||||
return mp_const_true;
|
return mp_const_true;
|
||||||
|
@ -39,6 +39,6 @@
|
|||||||
/*
|
/*
|
||||||
* Current storage version.
|
* Current storage version.
|
||||||
*/
|
*/
|
||||||
#define NORCOW_VERSION ((uint32_t)0x00000002)
|
#define NORCOW_VERSION ((uint32_t)0x00000003)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,7 +12,7 @@ def init(
|
|||||||
|
|
||||||
|
|
||||||
# extmod/modtrezorconfig/modtrezorconfig.c
|
# extmod/modtrezorconfig/modtrezorconfig.c
|
||||||
def unlock(pin: int, ext_salt: Optional[bytes]) -> bool:
|
def unlock(pin: str, ext_salt: Optional[bytes]) -> bool:
|
||||||
"""
|
"""
|
||||||
Attempts to unlock the storage with the given PIN and external salt.
|
Attempts to unlock the storage with the given PIN and external salt.
|
||||||
Returns True on success, False on failure.
|
Returns True on success, False on failure.
|
||||||
@ -20,7 +20,7 @@ def unlock(pin: int, ext_salt: Optional[bytes]) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
# extmod/modtrezorconfig/modtrezorconfig.c
|
# extmod/modtrezorconfig/modtrezorconfig.c
|
||||||
def check_pin(pin: int, ext_salt: Optional[bytes]) -> bool:
|
def check_pin(pin: str, ext_salt: Optional[bytes]) -> bool:
|
||||||
"""
|
"""
|
||||||
Check the given PIN with the given external salt.
|
Check the given PIN with the given external salt.
|
||||||
Returns True on success, False on failure.
|
Returns True on success, False on failure.
|
||||||
@ -57,8 +57,8 @@ def get_pin_rem() -> int:
|
|||||||
|
|
||||||
# extmod/modtrezorconfig/modtrezorconfig.c
|
# extmod/modtrezorconfig/modtrezorconfig.c
|
||||||
def change_pin(
|
def change_pin(
|
||||||
oldpin: int,
|
oldpin: str,
|
||||||
newpin: int,
|
newpin: str,
|
||||||
old_ext_salt: Optional[bytes],
|
old_ext_salt: Optional[bytes],
|
||||||
new_ext_salt: Optional[bytes],
|
new_ext_salt: Optional[bytes],
|
||||||
) -> bool:
|
) -> bool:
|
||||||
@ -68,7 +68,7 @@ def change_pin(
|
|||||||
|
|
||||||
|
|
||||||
# extmod/modtrezorconfig/modtrezorconfig.c
|
# extmod/modtrezorconfig/modtrezorconfig.c
|
||||||
def ensure_not_wipe_code(pin: int) -> None:
|
def ensure_not_wipe_code(pin: str) -> None:
|
||||||
"""
|
"""
|
||||||
Wipes the device if the entered PIN is the wipe code.
|
Wipes the device if the entered PIN is the wipe code.
|
||||||
"""
|
"""
|
||||||
@ -83,9 +83,9 @@ def has_wipe_code() -> bool:
|
|||||||
|
|
||||||
# extmod/modtrezorconfig/modtrezorconfig.c
|
# extmod/modtrezorconfig/modtrezorconfig.c
|
||||||
def change_wipe_code(
|
def change_wipe_code(
|
||||||
pin: int,
|
pin: str,
|
||||||
ext_salt: Optional[bytes],
|
ext_salt: Optional[bytes],
|
||||||
wipe_code: int,
|
wipe_code: str,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Change wipe code. Returns True on success, False on failure.
|
Change wipe code. Returns True on success, False on failure.
|
||||||
|
@ -3,7 +3,6 @@ import utime
|
|||||||
import storage.sd_salt
|
import storage.sd_salt
|
||||||
from trezor import config, ui, wire
|
from trezor import config, ui, wire
|
||||||
from trezor.messages import ButtonRequestType
|
from trezor.messages import ButtonRequestType
|
||||||
from trezor.pin import pin_to_int
|
|
||||||
from trezor.ui.components.tt.pin import CANCELLED, PinDialog
|
from trezor.ui.components.tt.pin import CANCELLED, PinDialog
|
||||||
from trezor.ui.components.tt.text import Text
|
from trezor.ui.components.tt.text import Text
|
||||||
from trezor.ui.popup import Popup
|
from trezor.ui.popup import Popup
|
||||||
@ -71,7 +70,7 @@ async def request_pin_and_sd_salt(
|
|||||||
) -> Tuple[str, Optional[bytearray]]:
|
) -> Tuple[str, Optional[bytearray]]:
|
||||||
if config.has_pin():
|
if config.has_pin():
|
||||||
pin = await request_pin(ctx, prompt, config.get_pin_rem(), allow_cancel)
|
pin = await request_pin(ctx, prompt, config.get_pin_rem(), allow_cancel)
|
||||||
config.ensure_not_wipe_code(pin_to_int(pin))
|
config.ensure_not_wipe_code(pin)
|
||||||
else:
|
else:
|
||||||
pin = ""
|
pin = ""
|
||||||
|
|
||||||
@ -98,7 +97,7 @@ async def verify_user_pin(
|
|||||||
|
|
||||||
if config.has_pin():
|
if config.has_pin():
|
||||||
pin = await request_pin(ctx, prompt, config.get_pin_rem(), allow_cancel)
|
pin = await request_pin(ctx, prompt, config.get_pin_rem(), allow_cancel)
|
||||||
config.ensure_not_wipe_code(pin_to_int(pin))
|
config.ensure_not_wipe_code(pin)
|
||||||
else:
|
else:
|
||||||
pin = ""
|
pin = ""
|
||||||
|
|
||||||
@ -106,7 +105,7 @@ async def verify_user_pin(
|
|||||||
salt = await request_sd_salt(ctx)
|
salt = await request_sd_salt(ctx)
|
||||||
except SdCardUnavailable:
|
except SdCardUnavailable:
|
||||||
raise wire.PinCancelled("SD salt is unavailable")
|
raise wire.PinCancelled("SD salt is unavailable")
|
||||||
if config.unlock(pin_to_int(pin), salt):
|
if config.unlock(pin, salt):
|
||||||
_last_successful_unlock = utime.ticks_ms()
|
_last_successful_unlock = utime.ticks_ms()
|
||||||
return
|
return
|
||||||
elif not config.has_pin():
|
elif not config.has_pin():
|
||||||
@ -116,7 +115,7 @@ async def verify_user_pin(
|
|||||||
pin = await request_pin(
|
pin = await request_pin(
|
||||||
ctx, "Wrong PIN, enter again", config.get_pin_rem(), allow_cancel
|
ctx, "Wrong PIN, enter again", config.get_pin_rem(), allow_cancel
|
||||||
)
|
)
|
||||||
if config.unlock(pin_to_int(pin), salt):
|
if config.unlock(pin, salt):
|
||||||
_last_successful_unlock = utime.ticks_ms()
|
_last_successful_unlock = utime.ticks_ms()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ from trezor import config, wire
|
|||||||
from trezor.crypto import bip39, slip39
|
from trezor.crypto import bip39, slip39
|
||||||
from trezor.messages import BackupType
|
from trezor.messages import BackupType
|
||||||
from trezor.messages.Success import Success
|
from trezor.messages.Success import Success
|
||||||
from trezor.pin import pin_to_int
|
|
||||||
from trezor.ui.layouts import confirm_action, require
|
from trezor.ui.layouts import confirm_action, require
|
||||||
|
|
||||||
from apps.management import backup_types
|
from apps.management import backup_types
|
||||||
@ -46,7 +45,7 @@ async def load_device(ctx, msg):
|
|||||||
storage.device.set_passphrase_enabled(msg.passphrase_protection)
|
storage.device.set_passphrase_enabled(msg.passphrase_protection)
|
||||||
storage.device.set_label(msg.label or "")
|
storage.device.set_label(msg.label or "")
|
||||||
if msg.pin:
|
if msg.pin:
|
||||||
config.change_pin(pin_to_int(""), pin_to_int(msg.pin), None, None)
|
config.change_pin("", msg.pin, None, None)
|
||||||
|
|
||||||
return Success(message="Device loaded")
|
return Success(message="Device loaded")
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
from storage.device import is_initialized
|
from storage.device import is_initialized
|
||||||
from trezor import config, ui, wire
|
from trezor import config, ui, wire
|
||||||
from trezor.messages.Success import Success
|
from trezor.messages.Success import Success
|
||||||
from trezor.pin import pin_to_int
|
|
||||||
from trezor.ui.components.tt.text import Text
|
from trezor.ui.components.tt.text import Text
|
||||||
from trezor.ui.layouts import require, show_success
|
from trezor.ui.layouts import require, show_success
|
||||||
|
|
||||||
@ -29,7 +28,7 @@ async def change_pin(ctx: wire.Context, msg: ChangePin) -> Success:
|
|||||||
|
|
||||||
# if changing pin, pre-check the entered pin before getting new pin
|
# if changing pin, pre-check the entered pin before getting new pin
|
||||||
if curpin and not msg.remove:
|
if curpin and not msg.remove:
|
||||||
if not config.check_pin(pin_to_int(curpin), salt):
|
if not config.check_pin(curpin, salt):
|
||||||
await error_pin_invalid(ctx)
|
await error_pin_invalid(ctx)
|
||||||
|
|
||||||
# get new pin
|
# get new pin
|
||||||
@ -39,7 +38,7 @@ async def change_pin(ctx: wire.Context, msg: ChangePin) -> Success:
|
|||||||
newpin = ""
|
newpin = ""
|
||||||
|
|
||||||
# write into storage
|
# write into storage
|
||||||
if not config.change_pin(pin_to_int(curpin), pin_to_int(newpin), salt, salt):
|
if not config.change_pin(curpin, newpin, salt, salt):
|
||||||
if newpin:
|
if newpin:
|
||||||
await error_pin_matches_wipe_code(ctx)
|
await error_pin_matches_wipe_code(ctx)
|
||||||
else:
|
else:
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
from storage.device import is_initialized
|
from storage.device import is_initialized
|
||||||
from trezor import config, ui, wire
|
from trezor import config, ui, wire
|
||||||
from trezor.messages.Success import Success
|
from trezor.messages.Success import Success
|
||||||
from trezor.pin import pin_to_int
|
|
||||||
from trezor.ui.components.tt.text import Text
|
from trezor.ui.components.tt.text import Text
|
||||||
from trezor.ui.layouts import require, show_success
|
from trezor.ui.layouts import require, show_success
|
||||||
from trezor.ui.popup import Popup
|
from trezor.ui.popup import Popup
|
||||||
@ -30,7 +29,7 @@ async def change_wipe_code(ctx: wire.Context, msg: ChangeWipeCode) -> Success:
|
|||||||
|
|
||||||
if not msg.remove:
|
if not msg.remove:
|
||||||
# Pre-check the entered PIN.
|
# Pre-check the entered PIN.
|
||||||
if config.has_pin() and not config.check_pin(pin_to_int(pin), salt):
|
if config.has_pin() and not config.check_pin(pin, salt):
|
||||||
await error_pin_invalid(ctx)
|
await error_pin_invalid(ctx)
|
||||||
|
|
||||||
# Get new wipe code.
|
# Get new wipe code.
|
||||||
@ -39,7 +38,7 @@ async def change_wipe_code(ctx: wire.Context, msg: ChangeWipeCode) -> Success:
|
|||||||
wipe_code = ""
|
wipe_code = ""
|
||||||
|
|
||||||
# Write into storage.
|
# Write into storage.
|
||||||
if not config.change_wipe_code(pin_to_int(pin), salt, pin_to_int(wipe_code)):
|
if not config.change_wipe_code(pin, salt, wipe_code):
|
||||||
await error_pin_invalid(ctx)
|
await error_pin_invalid(ctx)
|
||||||
|
|
||||||
if wipe_code:
|
if wipe_code:
|
||||||
|
@ -4,7 +4,6 @@ import storage.recovery
|
|||||||
from trezor import config, ui, wire, workflow
|
from trezor import config, ui, wire, workflow
|
||||||
from trezor.messages import ButtonRequestType
|
from trezor.messages import ButtonRequestType
|
||||||
from trezor.messages.Success import Success
|
from trezor.messages.Success import Success
|
||||||
from trezor.pin import pin_to_int
|
|
||||||
from trezor.ui.components.tt.text import Text
|
from trezor.ui.components.tt.text import Text
|
||||||
|
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
@ -47,14 +46,14 @@ async def recovery_device(ctx: wire.Context, msg: RecoveryDevice) -> Success:
|
|||||||
# for dry run pin needs to be entered
|
# for dry run pin needs to be entered
|
||||||
if msg.dry_run:
|
if msg.dry_run:
|
||||||
curpin, salt = await request_pin_and_sd_salt(ctx, "Enter PIN")
|
curpin, salt = await request_pin_and_sd_salt(ctx, "Enter PIN")
|
||||||
if not config.check_pin(pin_to_int(curpin), salt):
|
if not config.check_pin(curpin, salt):
|
||||||
await error_pin_invalid(ctx)
|
await error_pin_invalid(ctx)
|
||||||
|
|
||||||
if not msg.dry_run:
|
if not msg.dry_run:
|
||||||
# set up pin if requested
|
# set up pin if requested
|
||||||
if msg.pin_protection:
|
if msg.pin_protection:
|
||||||
newpin = await request_pin_confirm(ctx, allow_cancel=False)
|
newpin = await request_pin_confirm(ctx, allow_cancel=False)
|
||||||
config.change_pin(pin_to_int(""), pin_to_int(newpin), None, None)
|
config.change_pin("", newpin, None, None)
|
||||||
|
|
||||||
storage.device.set_passphrase_enabled(bool(msg.passphrase_protection))
|
storage.device.set_passphrase_enabled(bool(msg.passphrase_protection))
|
||||||
if msg.u2f_counter is not None:
|
if msg.u2f_counter is not None:
|
||||||
|
@ -6,7 +6,6 @@ from trezor.messages import BackupType
|
|||||||
from trezor.messages.EntropyAck import EntropyAck
|
from trezor.messages.EntropyAck import EntropyAck
|
||||||
from trezor.messages.EntropyRequest import EntropyRequest
|
from trezor.messages.EntropyRequest import EntropyRequest
|
||||||
from trezor.messages.Success import Success
|
from trezor.messages.Success import Success
|
||||||
from trezor.pin import pin_to_int
|
|
||||||
from trezor.ui.layouts import confirm_backup, confirm_reset_device, require
|
from trezor.ui.layouts import confirm_backup, confirm_reset_device, require
|
||||||
from trezor.ui.loader import LoadingAnimation
|
from trezor.ui.loader import LoadingAnimation
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ async def reset_device(ctx: wire.Context, msg: ResetDevice) -> Success:
|
|||||||
# request and set new PIN
|
# request and set new PIN
|
||||||
if msg.pin_protection:
|
if msg.pin_protection:
|
||||||
newpin = await request_pin_confirm(ctx)
|
newpin = await request_pin_confirm(ctx)
|
||||||
if not config.change_pin(pin_to_int(""), pin_to_int(newpin), None, None):
|
if not config.change_pin("", newpin, None, None):
|
||||||
raise wire.ProcessError("Failed to set PIN")
|
raise wire.ProcessError("Failed to set PIN")
|
||||||
|
|
||||||
# generate and display internal entropy
|
# generate and display internal entropy
|
||||||
|
@ -4,7 +4,6 @@ from trezor import config, ui, wire
|
|||||||
from trezor.crypto import random
|
from trezor.crypto import random
|
||||||
from trezor.messages import SdProtectOperationType
|
from trezor.messages import SdProtectOperationType
|
||||||
from trezor.messages.Success import Success
|
from trezor.messages.Success import Success
|
||||||
from trezor.pin import pin_to_int
|
|
||||||
from trezor.ui.components.tt.text import Text
|
from trezor.ui.components.tt.text import Text
|
||||||
from trezor.ui.layouts import require, show_success
|
from trezor.ui.layouts import require, show_success
|
||||||
|
|
||||||
@ -66,9 +65,9 @@ async def sd_protect_enable(ctx: wire.Context, msg: SdProtect) -> Success:
|
|||||||
|
|
||||||
# Get the current PIN.
|
# Get the current PIN.
|
||||||
if config.has_pin():
|
if config.has_pin():
|
||||||
pin = pin_to_int(await request_pin(ctx, "Enter PIN", config.get_pin_rem()))
|
pin = await request_pin(ctx, "Enter PIN", config.get_pin_rem())
|
||||||
else:
|
else:
|
||||||
pin = pin_to_int("")
|
pin = ""
|
||||||
|
|
||||||
# Check PIN and prepare salt file.
|
# Check PIN and prepare salt file.
|
||||||
salt, salt_auth_key, salt_tag = _make_salt()
|
salt, salt_auth_key, salt_tag = _make_salt()
|
||||||
@ -107,7 +106,7 @@ async def sd_protect_disable(ctx: wire.Context, msg: SdProtect) -> Success:
|
|||||||
pin, salt = await request_pin_and_sd_salt(ctx, "Enter PIN")
|
pin, salt = await request_pin_and_sd_salt(ctx, "Enter PIN")
|
||||||
|
|
||||||
# Check PIN and remove salt.
|
# Check PIN and remove salt.
|
||||||
if not config.change_pin(pin_to_int(pin), pin_to_int(pin), salt, None):
|
if not config.change_pin(pin, pin, salt, None):
|
||||||
await error_pin_invalid(ctx)
|
await error_pin_invalid(ctx)
|
||||||
|
|
||||||
storage.device.set_sd_salt_auth_key(None)
|
storage.device.set_sd_salt_auth_key(None)
|
||||||
@ -144,7 +143,7 @@ async def sd_protect_refresh(ctx: wire.Context, msg: SdProtect) -> Success:
|
|||||||
new_salt, new_auth_key, new_salt_tag = _make_salt()
|
new_salt, new_auth_key, new_salt_tag = _make_salt()
|
||||||
await _set_salt(ctx, new_salt, new_salt_tag, stage=True)
|
await _set_salt(ctx, new_salt, new_salt_tag, stage=True)
|
||||||
|
|
||||||
if not config.change_pin(pin_to_int(pin), pin_to_int(pin), old_salt, new_salt):
|
if not config.change_pin(pin, pin, old_salt, new_salt):
|
||||||
await error_pin_invalid(ctx)
|
await error_pin_invalid(ctx)
|
||||||
|
|
||||||
storage.device.set_sd_salt_auth_key(new_auth_key)
|
storage.device.set_sd_salt_auth_key(new_auth_key)
|
||||||
|
@ -4,10 +4,6 @@ if False:
|
|||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
|
||||||
def pin_to_int(pin: str) -> int:
|
|
||||||
return int("1" + pin)
|
|
||||||
|
|
||||||
|
|
||||||
_previous_progress: Optional[int] = None
|
_previous_progress: Optional[int] = None
|
||||||
_previous_seconds: Optional[int] = None
|
_previous_seconds: Optional[int] = None
|
||||||
keepalive_callback: Any = None
|
keepalive_callback: Any = None
|
||||||
|
@ -41,16 +41,40 @@ class PinInput(ui.Component):
|
|||||||
self.repaint = False
|
self.repaint = False
|
||||||
|
|
||||||
def render_pin(self) -> None:
|
def render_pin(self) -> None:
|
||||||
display.bar(0, 0, ui.WIDTH, 50, ui.BG)
|
MAX_LENGTH = const(14) # maximum length of displayed PIN
|
||||||
count = len(self.pin)
|
CONTD_MARK = "<"
|
||||||
BOX_WIDTH = const(240)
|
BOX_WIDTH = const(240)
|
||||||
DOT_SIZE = const(10)
|
DOT_SIZE = const(10)
|
||||||
PADDING = const(14)
|
PADDING = const(4)
|
||||||
RENDER_Y = const(20)
|
RENDER_Y = const(20)
|
||||||
render_x = (BOX_WIDTH - count * PADDING) // 2
|
TWITCH = const(3)
|
||||||
|
|
||||||
|
display.bar(0, 0, ui.WIDTH, 50, ui.BG)
|
||||||
|
|
||||||
|
if len(self.pin) > MAX_LENGTH:
|
||||||
|
contd_width = display.text_width(CONTD_MARK, ui.BOLD) + PADDING
|
||||||
|
twitch = TWITCH * (len(self.pin) % 2)
|
||||||
|
else:
|
||||||
|
contd_width = 0
|
||||||
|
twitch = 0
|
||||||
|
|
||||||
|
count = min(len(self.pin), MAX_LENGTH)
|
||||||
|
render_x = (BOX_WIDTH - count * (DOT_SIZE + PADDING) - contd_width) // 2
|
||||||
|
|
||||||
|
if contd_width:
|
||||||
|
display.text(
|
||||||
|
render_x, RENDER_Y + DOT_SIZE, CONTD_MARK, ui.BOLD, ui.GREY, ui.BG
|
||||||
|
)
|
||||||
|
|
||||||
for i in range(0, count):
|
for i in range(0, count):
|
||||||
display.bar_radius(
|
display.bar_radius(
|
||||||
render_x + i * PADDING, RENDER_Y, DOT_SIZE, DOT_SIZE, ui.GREY, ui.BG, 4
|
render_x + contd_width + twitch + i * (DOT_SIZE + PADDING),
|
||||||
|
RENDER_Y,
|
||||||
|
DOT_SIZE,
|
||||||
|
DOT_SIZE,
|
||||||
|
ui.GREY,
|
||||||
|
ui.BG,
|
||||||
|
4,
|
||||||
)
|
)
|
||||||
|
|
||||||
def render_prompt(self) -> None:
|
def render_prompt(self) -> None:
|
||||||
@ -82,7 +106,7 @@ class PinDialog(ui.Layout):
|
|||||||
prompt: str,
|
prompt: str,
|
||||||
subprompt: Optional[str],
|
subprompt: Optional[str],
|
||||||
allow_cancel: bool = True,
|
allow_cancel: bool = True,
|
||||||
maxlength: int = 9,
|
maxlength: int = 50,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.maxlength = maxlength
|
self.maxlength = maxlength
|
||||||
self.input = PinInput(prompt, subprompt, "")
|
self.input = PinInput(prompt, subprompt, "")
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from common import *
|
from common import *
|
||||||
from trezor.pin import pin_to_int
|
|
||||||
from trezor import config
|
from trezor import config
|
||||||
from storage import device
|
from storage import device
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
from common import *
|
from common import *
|
||||||
|
|
||||||
from trezor.crypto import random
|
from trezor.crypto import random
|
||||||
from trezor.pin import pin_to_int
|
|
||||||
|
|
||||||
from trezor import config
|
from trezor import config
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ class TestConfig(unittest.TestCase):
|
|||||||
def test_wipe(self):
|
def test_wipe(self):
|
||||||
config.init()
|
config.init()
|
||||||
config.wipe()
|
config.wipe()
|
||||||
self.assertEqual(config.unlock(pin_to_int(''), None), True)
|
self.assertEqual(config.unlock('', None), True)
|
||||||
config.set(1, 1, b'hello')
|
config.set(1, 1, b'hello')
|
||||||
config.set(1, 2, b'world')
|
config.set(1, 2, b'world')
|
||||||
v0 = config.get(1, 1)
|
v0 = config.get(1, 1)
|
||||||
@ -44,7 +43,7 @@ class TestConfig(unittest.TestCase):
|
|||||||
for _ in range(128):
|
for _ in range(128):
|
||||||
config.init()
|
config.init()
|
||||||
config.wipe()
|
config.wipe()
|
||||||
self.assertEqual(config.unlock(pin_to_int(''), None), True)
|
self.assertEqual(config.unlock('', None), True)
|
||||||
appid, key = random_entry()
|
appid, key = random_entry()
|
||||||
value = random.bytes(16)
|
value = random.bytes(16)
|
||||||
config.set(appid, key, value)
|
config.set(appid, key, value)
|
||||||
@ -58,7 +57,7 @@ class TestConfig(unittest.TestCase):
|
|||||||
def test_public(self):
|
def test_public(self):
|
||||||
config.init()
|
config.init()
|
||||||
config.wipe()
|
config.wipe()
|
||||||
self.assertEqual(config.unlock(pin_to_int(''), None), True)
|
self.assertEqual(config.unlock('', None), True)
|
||||||
|
|
||||||
appid, key = random_entry()
|
appid, key = random_entry()
|
||||||
|
|
||||||
@ -84,20 +83,46 @@ class TestConfig(unittest.TestCase):
|
|||||||
def test_change_pin(self):
|
def test_change_pin(self):
|
||||||
config.init()
|
config.init()
|
||||||
config.wipe()
|
config.wipe()
|
||||||
self.assertEqual(config.unlock(pin_to_int(''), None), True)
|
self.assertTrue(config.unlock('', None))
|
||||||
with self.assertRaises(RuntimeError):
|
|
||||||
config.set(PINAPP, PINKEY, b'value')
|
|
||||||
self.assertEqual(config.change_pin(pin_to_int('000'), pin_to_int('666'), None, None), False)
|
|
||||||
self.assertEqual(config.change_pin(pin_to_int(''), pin_to_int('000'), None, None), True)
|
|
||||||
self.assertEqual(config.get(PINAPP, PINKEY), None)
|
|
||||||
config.set(1, 1, b'value')
|
config.set(1, 1, b'value')
|
||||||
config.init()
|
PINS = ('123', '123', 'Trezor T', '3141592653589793238462643383279502884197', '')
|
||||||
self.assertEqual(config.unlock(pin_to_int('000'), None), True)
|
old_pin = ''
|
||||||
config.change_pin(pin_to_int('000'), pin_to_int(''), None, None)
|
for new_pin in PINS:
|
||||||
config.init()
|
self.assertTrue(config.unlock(old_pin, None))
|
||||||
self.assertEqual(config.unlock(pin_to_int('000'), None), False)
|
|
||||||
self.assertEqual(config.unlock(pin_to_int(''), None), True)
|
# The APP namespace which is reserved for storage related values is inaccessible even
|
||||||
self.assertEqual(config.get(1, 1), b'value')
|
# when unlocked.
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
config.set(PINAPP, PINKEY, b'value')
|
||||||
|
|
||||||
|
self.assertTrue(config.change_pin(old_pin, new_pin, None, None))
|
||||||
|
|
||||||
|
# Old PIN cannot be used to change the current PIN.
|
||||||
|
if old_pin != new_pin:
|
||||||
|
self.assertFalse(config.change_pin(old_pin, '666', None, None))
|
||||||
|
|
||||||
|
# Storage remains unlocked.
|
||||||
|
self.assertEqual(config.get(1, 1), b'value')
|
||||||
|
|
||||||
|
# The APP namespace which is reserved for storage related values is inaccessible even
|
||||||
|
# when unlocked.
|
||||||
|
self.assertEqual(config.get(PINAPP, PINKEY), None)
|
||||||
|
|
||||||
|
# Old PIN cannot be used to unlock storage.
|
||||||
|
if old_pin != new_pin:
|
||||||
|
config.init()
|
||||||
|
self.assertFalse(config.unlock(old_pin, None))
|
||||||
|
self.assertEqual(config.get(1, 1), None)
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
config.set(1, 1, b'new value')
|
||||||
|
|
||||||
|
# New PIN unlocks the storage.
|
||||||
|
self.assertTrue(config.unlock(new_pin, None))
|
||||||
|
self.assertEqual(config.get(1, 1), b'value')
|
||||||
|
|
||||||
|
# Lock the storage.
|
||||||
|
config.init()
|
||||||
|
old_pin = new_pin
|
||||||
|
|
||||||
def test_change_sd_salt(self):
|
def test_change_sd_salt(self):
|
||||||
salt1 = b"0123456789abcdef0123456789abcdef"
|
salt1 = b"0123456789abcdef0123456789abcdef"
|
||||||
@ -106,37 +131,37 @@ class TestConfig(unittest.TestCase):
|
|||||||
# Enable PIN and SD salt.
|
# Enable PIN and SD salt.
|
||||||
config.init()
|
config.init()
|
||||||
config.wipe()
|
config.wipe()
|
||||||
self.assertTrue(config.unlock(pin_to_int(''), None))
|
self.assertTrue(config.unlock('', None))
|
||||||
config.set(1, 1, b'value')
|
config.set(1, 1, b'value')
|
||||||
self.assertFalse(config.change_pin(pin_to_int(''), pin_to_int(''), salt1, None))
|
self.assertFalse(config.change_pin('', '', salt1, None))
|
||||||
self.assertTrue(config.change_pin(pin_to_int(''), pin_to_int('000'), None, salt1))
|
self.assertTrue(config.change_pin('', '000', None, salt1))
|
||||||
self.assertEqual(config.get(1, 1), b'value')
|
self.assertEqual(config.get(1, 1), b'value')
|
||||||
|
|
||||||
# Disable PIN and change SD salt.
|
# Disable PIN and change SD salt.
|
||||||
config.init()
|
config.init()
|
||||||
self.assertFalse(config.unlock(pin_to_int('000'), None))
|
self.assertFalse(config.unlock('000', None))
|
||||||
self.assertIsNone(config.get(1, 1))
|
self.assertIsNone(config.get(1, 1))
|
||||||
self.assertTrue(config.unlock(pin_to_int('000'), salt1))
|
self.assertTrue(config.unlock('000', salt1))
|
||||||
self.assertTrue(config.change_pin(pin_to_int('000'), pin_to_int(''), salt1, salt2))
|
self.assertTrue(config.change_pin('000', '', salt1, salt2))
|
||||||
self.assertEqual(config.get(1, 1), b'value')
|
self.assertEqual(config.get(1, 1), b'value')
|
||||||
|
|
||||||
# Disable SD salt.
|
# Disable SD salt.
|
||||||
config.init()
|
config.init()
|
||||||
self.assertFalse(config.unlock(pin_to_int('000'), salt2))
|
self.assertFalse(config.unlock('000', salt2))
|
||||||
self.assertIsNone(config.get(1, 1))
|
self.assertIsNone(config.get(1, 1))
|
||||||
self.assertTrue(config.unlock(pin_to_int(''), salt2))
|
self.assertTrue(config.unlock('', salt2))
|
||||||
self.assertTrue(config.change_pin(pin_to_int(''), pin_to_int(''), salt2, None))
|
self.assertTrue(config.change_pin('', '', salt2, None))
|
||||||
self.assertEqual(config.get(1, 1), b'value')
|
self.assertEqual(config.get(1, 1), b'value')
|
||||||
|
|
||||||
# Check that PIN and SD salt are disabled.
|
# Check that PIN and SD salt are disabled.
|
||||||
config.init()
|
config.init()
|
||||||
self.assertTrue(config.unlock(pin_to_int(''), None))
|
self.assertTrue(config.unlock('', None))
|
||||||
self.assertEqual(config.get(1, 1), b'value')
|
self.assertEqual(config.get(1, 1), b'value')
|
||||||
|
|
||||||
def test_set_get(self):
|
def test_set_get(self):
|
||||||
config.init()
|
config.init()
|
||||||
config.wipe()
|
config.wipe()
|
||||||
self.assertEqual(config.unlock(pin_to_int(''), None), True)
|
self.assertEqual(config.unlock('', None), True)
|
||||||
for _ in range(32):
|
for _ in range(32):
|
||||||
appid, key = random_entry()
|
appid, key = random_entry()
|
||||||
value = random.bytes(128)
|
value = random.bytes(128)
|
||||||
@ -147,7 +172,7 @@ class TestConfig(unittest.TestCase):
|
|||||||
def test_compact(self):
|
def test_compact(self):
|
||||||
config.init()
|
config.init()
|
||||||
config.wipe()
|
config.wipe()
|
||||||
self.assertEqual(config.unlock(pin_to_int(''), None), True)
|
self.assertEqual(config.unlock('', None), True)
|
||||||
appid, key = 1, 1
|
appid, key = 1, 1
|
||||||
for _ in range(259):
|
for _ in range(259):
|
||||||
value = random.bytes(259)
|
value = random.bytes(259)
|
||||||
@ -158,7 +183,7 @@ class TestConfig(unittest.TestCase):
|
|||||||
def test_get_default(self):
|
def test_get_default(self):
|
||||||
config.init()
|
config.init()
|
||||||
config.wipe()
|
config.wipe()
|
||||||
self.assertEqual(config.unlock(pin_to_int(''), None), True)
|
self.assertEqual(config.unlock('', None), True)
|
||||||
for _ in range(128):
|
for _ in range(128):
|
||||||
appid, key = random_entry()
|
appid, key = random_entry()
|
||||||
value = config.get(appid, key)
|
value = config.get(appid, key)
|
||||||
|
Loading…
Reference in New Issue
Block a user