1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-04 21:48:17 +00:00

Compare commits

...

5 Commits

Author SHA1 Message Date
matejcik
05a88584be
Merge aa718c58a8 into 13df961317 2024-12-02 22:28:03 +01:00
Ioan Bizău
13df961317 refactor(core/ui): introduce show_danger
This is a unified interface for flow_warning_hi_prio,
which was available only on Mercury before.

[no changelog]
2024-12-02 22:28:00 +01:00
matejcik
aa718c58a8 feat(core): introduce storage insecure mode
reduces the number of PIN iterations and avoids erasing the other
storage bank -- if a test ever overruns, it will probably RSOD out, but
that's unlikely to happen
2024-12-02 11:19:11 +01:00
matejcik
5635816076 build(core): correctly propagate DISABLE_OPTIGA to kernel 2024-12-02 11:19:11 +01:00
matejcik
eb0ecd794d feat(core): disable animations in debug firmware by default
This makes it possible to run HW tests on the T3T1 where animations mess
things up. It also speeds up HW tests on other models slightly.

export TREZOR_DISABLE_ANIMATION=0 to build a debug firmware with
animations enabled
2024-12-02 11:19:11 +01:00
19 changed files with 519 additions and 393 deletions

View File

@ -31,6 +31,7 @@ PYOPT ?= 1
BITCOIN_ONLY ?= 0
BOOTLOADER_QA ?= 0
BOOTLOADER_DEVEL ?= 0
DISABLE_OPTIGA ?= 0
TREZOR_MODEL ?= T
TREZOR_MEMPERF ?= 0
ADDRESS_SANITIZER ?= 0
@ -41,6 +42,8 @@ THP ?= 0
BENCHMARK ?= 0
TREZOR_EMULATOR_DEBUGGABLE ?= 0
QUIET_MODE ?= 0
TREZOR_DISABLE_ANIMATION ?= $(if $(filter 0,$(PYOPT)),1,0)
STORAGE_INSECURE_TESTING_MODE ?= 0
# OpenOCD interface default. Alternative: ftdi/olimex-arm-usb-tiny-h
OPENOCD_INTERFACE ?= stlink
@ -142,7 +145,9 @@ SCONS_VARS = \
PRODUCTION="$(PRODUCTION)" \
PYOPT="$(PYOPT)" \
QUIET_MODE="$(QUIET_MODE)" \
STORAGE_INSECURE_TESTING_MODE="$(STORAGE_INSECURE_TESTING_MODE)" \
THP="$(THP)" \
TREZOR_DISABLE_ANIMATION="$(TREZOR_DISABLE_ANIMATION)" \
TREZOR_EMULATOR_ASAN="$(ADDRESS_SANITIZER)" \
TREZOR_EMULATOR_DEBUGGABLE=$(TREZOR_EMULATOR_DEBUGGABLE) \
TREZOR_MEMPERF="$(TREZOR_MEMPERF)" \

View File

@ -18,6 +18,14 @@ HW_REVISION = ARGUMENTS.get('HW_REVISION', None)
THP = ARGUMENTS.get('THP', '0') == '1' # Trezor-Host Protocol
MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL)
BENCHMARK = ARGUMENTS.get('BENCHMARK', '0') == '1'
DISABLE_ANIMATION = ARGUMENTS.get('TREZOR_DISABLE_ANIMATION', '0') == '1'
STORAGE_INSECURE_TESTING_MODE = ARGUMENTS.get('STORAGE_INSECURE_TESTING_MODE', '0') == '1'
if STORAGE_INSECURE_TESTING_MODE and PRODUCTION:
raise RuntimeError("STORAGE_INSECURE_TESTING_MODE cannot be used in production")
if STORAGE_INSECURE_TESTING_MODE:
DISABLE_OPTIGA = True
PYOPT = "0"
if BENCHMARK and PYOPT != '0':
print("BENCHMARK=1 works only with PYOPT=0.")
@ -30,7 +38,9 @@ FEATURE_FLAGS = {
}
FEATURES_WANTED = ["input", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic"]
if DISABLE_OPTIGA and PYOPT == '0':
if DISABLE_OPTIGA:
if PYOPT != '0':
raise RuntimeError("DISABLE_OPTIGA requires PYOPT=0")
FEATURES_WANTED.remove("optiga")
CCFLAGS_MOD = ''
@ -69,6 +79,7 @@ CPPDEFINES_MOD += [
('USE_CARDANO', '1' if EVERYTHING else '0'),
('USE_NEM', '1' if (EVERYTHING and TREZOR_MODEL == "T") else '0'),
('USE_EOS', '1' if (EVERYTHING and TREZOR_MODEL == "T") else '0'),
('DISABLE_ANIMATION', '1' if DISABLE_ANIMATION else '0'),
]
SOURCE_MOD += [
'embed/upymod/trezorobj.c',
@ -367,6 +378,9 @@ if THP:
'vendor/trezor-crypto/elligator2.c',
]
if STORAGE_INSECURE_TESTING_MODE:
CPPDEFINES_MOD += ['STORAGE_INSECURE_TESTING_MODE']
ui.init_ui(TREZOR_MODEL, "firmware", CPPDEFINES_MOD, SOURCE_MOD, RUST_UI_FEATURES)
SOURCE_QSTR = SOURCE_MOD + SOURCE_MICROPYTHON + SOURCE_MICROPYTHON_SPEED
@ -873,6 +887,14 @@ elif 'STM32U5G9xx' in CPPDEFINES_HAL or 'STM32U585xx' in CPPDEFINES_HAL:
else:
raise Exception("Unknown MCU")
if STORAGE_INSECURE_TESTING_MODE:
INSECURE_TESTING_MODE_STR = """
#########################################################
# STORAGE_INSECURE_TESTING_MODE enabled, DO NOT USE #
#########################################################
"""
action_bin.append(INSECURE_TESTING_MODE_STR)
program_bin = env.Command(
target='firmware.bin',
source=program_elf,

View File

@ -16,6 +16,13 @@ DISABLE_OPTIGA = ARGUMENTS.get('DISABLE_OPTIGA', '0') == '1'
HW_REVISION = ARGUMENTS.get('HW_REVISION', None)
THP = ARGUMENTS.get('THP', '0') == '1' # Trezor-Host Protocol
STORAGE_INSECURE_TESTING_MODE = ARGUMENTS.get('STORAGE_INSECURE_TESTING_MODE', '0') == '1'
if STORAGE_INSECURE_TESTING_MODE and PRODUCTION:
raise RuntimeError("STORAGE_INSECURE_TESTING_MODE cannot be used in production")
if STORAGE_INSECURE_TESTING_MODE:
DISABLE_OPTIGA = True
PYOPT = "0"
FEATURE_FLAGS = {
"RDI": True,
"SECP256K1_ZKP": True, # required for trezor.crypto.curve.bip340 (BIP340/Taproot)
@ -24,7 +31,10 @@ FEATURE_FLAGS = {
}
FEATURES_WANTED = ["input", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic"]
if DISABLE_OPTIGA and PYOPT == '0':
if DISABLE_OPTIGA:
# TODO use PYOPT instead of PRODUCTION, same as in firmware, blocked on #4253
if PRODUCTION:
raise RuntimeError("DISABLE_OPTIGA requires non-production build")
FEATURES_WANTED.remove("optiga")
CCFLAGS_MOD = ''
@ -235,6 +245,8 @@ if THP:
'vendor/trezor-crypto/elligator2.c',
]
if STORAGE_INSECURE_TESTING_MODE:
CPPDEFINES_MOD += ['STORAGE_INSECURE_TESTING_MODE']
env = Environment(
ENV=os.environ,
@ -411,6 +423,14 @@ action_bin=[
'$CP $TARGET ' + BINARY_NAME,
]
if STORAGE_INSECURE_TESTING_MODE:
INSECURE_TESTING_MODE_STR = """
#########################################################
# STORAGE_INSECURE_TESTING_MODE enabled, DO NOT USE #
#########################################################
"""
action_bin.append(INSECURE_TESTING_MODE_STR)
program_bin = env.Command(
target='kernel.bin',
source=program_elf,

View File

@ -262,7 +262,6 @@ static void _librust_qstrs(void) {
MP_QSTR_flow_request_number;
MP_QSTR_flow_request_passphrase;
MP_QSTR_flow_show_share_words;
MP_QSTR_flow_warning_hi_prio;
MP_QSTR_get_language;
MP_QSTR_get_transition_out;
MP_QSTR_haptic_feedback__disable;
@ -652,6 +651,7 @@ static void _librust_qstrs(void) {
MP_QSTR_share_words__wrote_down_all;
MP_QSTR_show_address_details;
MP_QSTR_show_checklist;
MP_QSTR_show_danger;
MP_QSTR_show_error;
MP_QSTR_show_group_share_success;
MP_QSTR_show_homescreen;

View File

@ -12,10 +12,10 @@ pub mod prompt_backup;
pub mod request_number;
pub mod request_passphrase;
pub mod set_brightness;
pub mod show_danger;
pub mod show_share_words;
pub mod show_tutorial;
pub mod util;
pub mod warning_hi_prio;
pub use confirm_action::{
new_confirm_action, new_confirm_action_simple, ConfirmActionExtra, ConfirmActionMenuStrings,
@ -34,7 +34,7 @@ pub use prompt_backup::PromptBackup;
pub use request_number::RequestNumber;
pub use request_passphrase::RequestPassphrase;
pub use set_brightness::SetBrightness;
pub use show_danger::ShowDanger;
pub use show_share_words::ShowShareWords;
pub use show_tutorial::ShowTutorial;
pub use util::{ConfirmBlobParams, ShowInfoParams};
pub use warning_hi_prio::WarningHiPrio;

View File

@ -22,13 +22,13 @@ use super::super::{
};
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum WarningHiPrio {
pub enum ShowDanger {
Message,
Menu,
Cancelled,
}
impl FlowController for WarningHiPrio {
impl FlowController for ShowDanger {
#[inline]
fn index(&'static self) -> usize {
*self as usize
@ -57,7 +57,7 @@ impl FlowController for WarningHiPrio {
const EXTRA_PADDING: i16 = 6;
pub fn new_warning_hi_prio(
pub fn new_show_danger(
title: TString<'static>,
description: TString<'static>,
value: TString<'static>,
@ -106,9 +106,9 @@ pub fn new_warning_hi_prio(
.with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREY_DARK)
.map(|_| Some(FlowMsg::Cancelled));
let res = SwipeFlow::new(&WarningHiPrio::Message)?
.with_page(&WarningHiPrio::Message, content_message)?
.with_page(&WarningHiPrio::Menu, content_menu)?
.with_page(&WarningHiPrio::Cancelled, content_cancelled)?;
let res = SwipeFlow::new(&ShowDanger::Message)?
.with_page(&ShowDanger::Message, content_message)?
.with_page(&ShowDanger::Menu, content_menu)?
.with_page(&ShowDanger::Cancelled, content_cancelled)?;
Ok(res)
}

View File

@ -1491,7 +1491,7 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
panic!();
}
extern "C" fn new_warning_hi_prio(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
extern "C" fn new_show_danger(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
@ -1501,8 +1501,7 @@ extern "C" fn new_warning_hi_prio(n_args: usize, args: *const Obj, kwargs: *mut
.unwrap_or_else(|_| Obj::const_none())
.try_into_option()?;
let flow =
flow::warning_hi_prio::new_warning_hi_prio(title, description, value, verb_cancel)?;
let flow = flow::show_danger::new_show_danger(title, description, value, verb_cancel)?;
Ok(LayoutObj::new_root(flow)?.into())
};
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -1717,6 +1716,16 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// """Warning modal. No buttons shown when `button` is empty string."""
Qstr::MP_QSTR_show_warning => obj_fn_kw!(0, new_show_warning).as_obj(),
/// def show_danger(
/// *,
/// title: str,
/// description: str,
/// value: str = "",
/// verb_cancel: str | None = None,
/// ) -> LayoutObj[UiResult]:
/// """Warning modal that makes it easier to cancel than to continue."""
Qstr::MP_QSTR_show_danger => obj_fn_kw!(0, new_show_danger).as_obj(),
/// def show_success(
/// *,
/// title: str,
@ -1971,16 +1980,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// """Get address / receive funds."""
Qstr::MP_QSTR_flow_get_address => obj_fn_kw!(0, new_get_address).as_obj(),
/// def flow_warning_hi_prio(
/// *,
/// title: str,
/// description: str,
/// value: str = "",
/// verb_cancel: str | None = None,
/// ) -> LayoutObj[UiResult]:
/// """Warning modal with multiple steps to confirm."""
Qstr::MP_QSTR_flow_warning_hi_prio => obj_fn_kw!(0, new_warning_hi_prio).as_obj(),
/// def flow_confirm_output(
/// *,
/// title: str | None,

View File

@ -410,6 +410,9 @@ STATIC mp_obj_tuple_t mod_trezorutils_version_obj = {
/// """UI layout identifier ("tt" for model T, "tr" for models One and R)."""
/// USE_THP: bool
/// """Whether the firmware supports Trezor-Host Protocol (version 2)."""
/// if __debug__:
/// DISABLE_ANIMATION: bool
/// """Whether the firmware should disable animations."""
STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorutils)},
@ -502,6 +505,13 @@ STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = {
#else
#error Unknown layout
#endif
#if !PYOPT
#if DISABLE_ANIMATION
{MP_ROM_QSTR(MP_QSTR_DISABLE_ANIMATION), mp_const_true},
#else
{MP_ROM_QSTR(MP_QSTR_DISABLE_ANIMATION), mp_const_false},
#endif // TREZOR_DISABLE_ANIMATION
#endif // PYOPT
};
STATIC MP_DEFINE_CONST_DICT(mp_module_trezorutils_globals,

View File

@ -216,6 +216,17 @@ def show_warning(
"""Warning modal. No buttons shown when `button` is empty string."""
# rust/src/ui/model_mercury/layout.rs
def show_danger(
*,
title: str,
description: str,
value: str = "",
verb_cancel: str | None = None,
) -> LayoutObj[UiResult]:
"""Warning modal that makes it easier to cancel than to continue."""
# rust/src/ui/model_mercury/layout.rs
def show_success(
*,
@ -497,17 +508,6 @@ def flow_get_address(
"""Get address / receive funds."""
# rust/src/ui/model_mercury/layout.rs
def flow_warning_hi_prio(
*,
title: str,
description: str,
value: str = "",
verb_cancel: str | None = None,
) -> LayoutObj[UiResult]:
"""Warning modal with multiple steps to confirm."""
# rust/src/ui/model_mercury/layout.rs
def flow_confirm_output(
*,

View File

@ -152,3 +152,6 @@ UI_LAYOUT: str
"""UI layout identifier ("tt" for model T, "tr" for models One and R)."""
USE_THP: bool
"""Whether the firmware supports Trezor-Host Protocol (version 2)."""
if __debug__:
DISABLE_ANIMATION: bool
"""Whether the firmware should disable animations."""

View File

@ -24,7 +24,7 @@ else:
if __debug__:
trezorui2.disable_animation(bool(utils.DISABLE_ANIMATION))
trezorui2.disable_animation(utils.DISABLE_ANIMATION)
# all rendering is done through a singleton of `Display`

View File

@ -119,29 +119,27 @@ def confirm_path_warning(
if not path_type
else f"{TR.words__unknown} {path_type.lower()}."
)
return raise_if_not_confirmed(
trezorui2.flow_warning_hi_prio(
title=f"{TR.words__warning}!", description=description, value=path
),
return show_danger(
"path_warning",
description,
value=path,
verb_cancel=TR.words__cancel_and_exit,
br_code=ButtonRequestType.UnknownDerivationPath,
)
def confirm_multisig_warning() -> Awaitable[None]:
return raise_if_not_confirmed(
trezorui2.flow_warning_hi_prio(
title=f"{TR.words__important}!",
description=TR.send__receiving_to_multisig,
),
return show_danger(
"warning_multisig",
br_code=ButtonRequestType.Warning,
TR.send__receiving_to_multisig,
title=TR.words__important,
verb_cancel=TR.words__cancel_and_exit,
)
def confirm_multisig_different_paths_warning() -> Awaitable[None]:
return raise_if_not_confirmed(
trezorui2.flow_warning_hi_prio(
trezorui2.show_danger(
title=f"{TR.words__important}!",
description="Using different paths for different XPUBs.",
),
@ -327,6 +325,28 @@ def show_warning(
)
def show_danger(
br_name: str,
content: str,
value: str | None = None,
title: str | None = None,
verb_cancel: str | None = None,
br_code: ButtonRequestType = ButtonRequestType.Warning,
) -> Awaitable[None]:
title = title or TR.words__warning
verb_cancel = verb_cancel or TR.buttons__cancel
return raise_if_not_confirmed(
trezorui2.show_danger(
title=title,
description=content,
value=(value or ""),
verb_cancel=verb_cancel,
),
br_name,
br_code,
)
def show_success(
br_name: str,
content: str,
@ -724,14 +744,10 @@ def _confirm_summary(
if not utils.BITCOIN_ONLY:
def confirm_ethereum_unknown_contract_warning() -> Awaitable[None]:
return raise_if_not_confirmed(
trezorui2.flow_warning_hi_prio(
title=TR.words__warning,
description=TR.ethereum__unknown_contract_address,
verb_cancel=TR.send__cancel_sign,
),
return show_danger(
"unknown_contract_warning",
ButtonRequestType.Warning,
TR.ethereum__unknown_contract_address,
verb_cancel=TR.send__cancel_sign,
)
async def confirm_ethereum_tx(

View File

@ -420,6 +420,24 @@ def show_warning(
)
def show_danger(
br_name: str,
content: str,
value: str | None = None,
title: str | None = None,
verb_cancel: str | None = None,
br_code: ButtonRequestType = ButtonRequestType.Warning,
) -> Awaitable[ui.UiResult]:
title = title or TR.words__warning
return show_warning(
br_name,
title,
content,
TR.words__continue_anyway,
br_code=br_code,
)
def show_success(
br_name: str,
content: str,
@ -564,7 +582,6 @@ def confirm_blob(
title: str,
data: bytes | str,
description: str | None = None,
text_mono: bool = True,
subtitle: str | None = None,
verb: str | None = None,
verb_cancel: str | None = None, # icon
@ -815,11 +832,8 @@ def confirm_total(
if not utils.BITCOIN_ONLY:
def confirm_ethereum_unknown_contract_warning() -> Awaitable[ui.UiResult]:
return show_warning(
"unknown_contract_warning",
TR.words__warning,
TR.ethereum__unknown_contract_address_short,
TR.words__continue_anyway,
return show_danger(
"unknown_contract_warning", TR.ethereum__unknown_contract_address_short
)
async def confirm_ethereum_staking_tx(

View File

@ -372,6 +372,22 @@ def show_warning(
)
def show_danger(
br_name: str,
content: str,
value: str | None = None,
title: str | None = None,
verb_cancel: str | None = None,
br_code: ButtonRequestType = ButtonRequestType.Warning,
) -> Awaitable[None]:
return show_warning(
br_name,
content,
TR.words__continue_anyway_question,
br_code=br_code,
)
def show_success(
br_name: str,
content: str,
@ -779,10 +795,8 @@ def _confirm_summary(
if not utils.BITCOIN_ONLY:
def confirm_ethereum_unknown_contract_warning() -> Awaitable[None]:
return show_warning(
"unknown_contract_warning",
TR.ethereum__unknown_contract_address_short,
TR.words__continue_anyway_question,
return show_danger(
"unknown_contract_warning", TR.ethereum__unknown_contract_address_short
)
async def confirm_ethereum_tx(

View File

@ -33,17 +33,20 @@ from trezorutils import ( # noqa: F401
)
from typing import TYPE_CHECKING
DISABLE_ANIMATION = 0
if __debug__:
if EMULATOR:
import uos
DISABLE_ANIMATION = int(uos.getenv("TREZOR_DISABLE_ANIMATION") or "0")
LOG_MEMORY = int(uos.getenv("TREZOR_LOG_MEMORY") or "0")
DISABLE_ANIMATION = uos.getenv("TREZOR_DISABLE_ANIMATION") == "1"
LOG_MEMORY = uos.getenv("TREZOR_LOG_MEMORY") == "1"
else:
from trezorutils import DISABLE_ANIMATION # noqa: F401
LOG_MEMORY = 0
else:
DISABLE_ANIMATION = False
if TYPE_CHECKING:
from typing import Any, Iterator, Protocol, Sequence, TypeVar

View File

@ -284,11 +284,15 @@ void norcow_wipe(void) {
// Erase the active sector first, because it contains sensitive data.
erase_sector(norcow_active_sector, sectrue);
#if STORAGE_INSECURE_TESTING_MODE && !PRODUCTION
// skip erasing inactive sectors
#else
for (uint8_t i = 0; i < NORCOW_SECTOR_COUNT; i++) {
if (i != norcow_active_sector) {
erase_sector(i, secfalse);
}
}
#endif
norcow_active_version = NORCOW_VERSION;
norcow_write_sector = norcow_active_sector;
norcow_free_offset = NORCOW_STORAGE_START;

View File

@ -86,8 +86,12 @@ const uint32_t V0_PIN_EMPTY = 1;
// up constant storage space.
#define MAX_WIPE_CODE_LEN 50
#if STORAGE_INSECURE_TESTING_MODE && !PRODUCTION
#define PIN_ITER_COUNT 1
#else
// The total number of iterations to use in PBKDF2.
#define PIN_ITER_COUNT 20000
#endif
// The minimum number of milliseconds between progress updates.
#define MIN_PROGRESS_UPDATE_MS 100

View File

@ -2,3 +2,15 @@
#include <stdint.h>
uint32_t hamming_weight(uint32_t value);
#ifndef STORAGE_INSECURE_TESTING_MODE
#define STORAGE_INSECURE_TESTING_MODE 0
#endif
#if STORAGE_INSECURE_TESTING_MODE
#if PRODUCTION
#error "STORAGE_INSECURE_TESTING_MODE can't be used in production"
#else
#pragma message("STORAGE IS INSECURE DO NOT USE THIS IN PRODUCTION")
#endif
#endif

File diff suppressed because it is too large Load Diff