1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-06-05 07:38:46 +00:00

Merge branch 'release/25.05' into ibz/merge-release-25.05

This commit is contained in:
Ioan Bizău 2025-05-23 11:05:50 +02:00
commit 8a5f599522
32 changed files with 447 additions and 52 deletions

View File

@ -1 +1 @@
2025-02-07T18:39:08+00:00
2025-03-04T12:16:03+00:00

View File

@ -43,6 +43,7 @@
"1.11.2": ["T1B1"],
"1.12.1": ["T1B1"],
"1.13.0": ["T1B1"],
"1.13.1": ["T1B1"],
"2.0.5": ["T2T1"],
"2.0.6": ["T2T1"],
"2.0.7": ["T2T1"],
@ -80,6 +81,7 @@
"2.8.3": ["T3B1", "T3T1"],
"2.8.7": ["T2B1", "T2T1", "T3B1", "T3T1"],
"2.8.8": ["T2T1"],
"2.8.9": ["T2B1", "T2T1", "T3B1", "T3T1"]
"2.8.9": ["T2B1", "T2T1", "T3B1", "T3T1"],
"2.8.10": ["T2B1", "T2T1", "T3B1", "T3T1"]
}
}

View File

@ -1 +0,0 @@
Add Nostr support (in debug mode only!).

View File

@ -1 +0,0 @@
Replaced "next page" icon with "..." ellipsis when confirming long message.

View File

@ -1 +0,0 @@
[T2T1] Fixed upgrade confirmation text overflow.

View File

@ -1 +0,0 @@
[T2T1] Fixed Solana staking dialog fonts.

View File

@ -1 +0,0 @@
[T2B1,T3B1] Fixed Solana staking dialog title.

View File

@ -1 +0,0 @@
Updated EIP-1559 fee-related labels.

View File

@ -1 +0,0 @@
Allow firmware upgrade even if language change failed.

View File

@ -1 +0,0 @@
[T3T1] Visual cues to distinguish unlocked state on Homescreen.

View File

@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [2.8.10] (21st May 2025)
### Added
- Add Nostr support (in debug mode only!). [#4160]
- Solana: rent fee calculation [#4933]
- Solana: loadable token definitions [#3541]
### Fixed
- Replaced "next page" icon with "..." ellipsis when confirming long message. [#4623]
- Fixed Solana staking dialog title. [#4787]
- Updated EIP-1559 fee-related labels. [#4819]
- Allow firmware upgrade even if language change failed. [#4827]
- Solana: fees calculation is now exact [#4965]
## [2.8.9] (19th March 2025)
### Added
@ -1033,6 +1047,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4142]: https://github.com/trezor/trezor-firmware/pull/4142
[#4151]: https://github.com/trezor/trezor-firmware/pull/4151
[#4155]: https://github.com/trezor/trezor-firmware/pull/4155
[#4160]: https://github.com/trezor/trezor-firmware/pull/4160
[#4161]: https://github.com/trezor/trezor-firmware/pull/4161
[#4165]: https://github.com/trezor/trezor-firmware/pull/4165
[#4167]: https://github.com/trezor/trezor-firmware/pull/4167
@ -1057,4 +1072,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4541]: https://github.com/trezor/trezor-firmware/pull/4541
[#4560]: https://github.com/trezor/trezor-firmware/pull/4560
[#4571]: https://github.com/trezor/trezor-firmware/pull/4571
[#1658739]: https://github.com/trezor/trezor-firmware/pull/1658739
[#4623]: https://github.com/trezor/trezor-firmware/pull/4623
[#4665]: https://github.com/trezor/trezor-firmware/pull/4665
[#4771]: https://github.com/trezor/trezor-firmware/pull/4771
[#4786]: https://github.com/trezor/trezor-firmware/pull/4786
[#4787]: https://github.com/trezor/trezor-firmware/pull/4787
[#4819]: https://github.com/trezor/trezor-firmware/pull/4819
[#4827]: https://github.com/trezor/trezor-firmware/pull/4827
[#4964]: https://github.com/trezor/trezor-firmware/pull/4964

View File

@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [2.8.10] (21st May 2025)
### Added
- Add Nostr support (in debug mode only!). [#4160]
- Solana: rent fee calculation [#4933]
- Solana: loadable token definitions [#3541]
### Fixed
- Replaced "next page" icon with "..." ellipsis when confirming long message. [#4623]
- Fixed upgrade confirmation text overflow. [#4771]
- Fixed Solana staking dialog fonts. [#4786]
- Updated EIP-1559 fee-related labels. [#4819]
- Allow firmware upgrade even if language change failed. [#4827]
- Solana: fees calculation is now exact [#4965]
## [2.8.9] (19th March 2025)
### Added
@ -1031,6 +1046,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4142]: https://github.com/trezor/trezor-firmware/pull/4142
[#4151]: https://github.com/trezor/trezor-firmware/pull/4151
[#4155]: https://github.com/trezor/trezor-firmware/pull/4155
[#4160]: https://github.com/trezor/trezor-firmware/pull/4160
[#4161]: https://github.com/trezor/trezor-firmware/pull/4161
[#4165]: https://github.com/trezor/trezor-firmware/pull/4165
[#4167]: https://github.com/trezor/trezor-firmware/pull/4167
@ -1055,4 +1071,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4541]: https://github.com/trezor/trezor-firmware/pull/4541
[#4560]: https://github.com/trezor/trezor-firmware/pull/4560
[#4571]: https://github.com/trezor/trezor-firmware/pull/4571
[#1658739]: https://github.com/trezor/trezor-firmware/pull/1658739
[#4623]: https://github.com/trezor/trezor-firmware/pull/4623
[#4665]: https://github.com/trezor/trezor-firmware/pull/4665
[#4771]: https://github.com/trezor/trezor-firmware/pull/4771
[#4786]: https://github.com/trezor/trezor-firmware/pull/4786
[#4787]: https://github.com/trezor/trezor-firmware/pull/4787
[#4819]: https://github.com/trezor/trezor-firmware/pull/4819
[#4827]: https://github.com/trezor/trezor-firmware/pull/4827
[#4964]: https://github.com/trezor/trezor-firmware/pull/4964

View File

@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [2.8.10] (21st May 2025)
### Added
- Upgrade bundled bootloader to 2.1.10.
- Add Nostr support (in debug mode only!). [#4160]
- Solana: rent fee calculation [#4933]
- Solana: loadable token definitions [#3541]
### Fixed
- Replaced "next page" icon with "..." ellipsis when confirming long message. [#4623]
- Fixed Solana staking dialog title. [#4787]
- Updated EIP-1559 fee-related labels. [#4819]
- Allow firmware upgrade even if language change failed. [#4827]
- Solana: fees calculation is now exact [#4965]
## [2.8.9] (19th March 2025)
### Added
@ -1024,6 +1039,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4142]: https://github.com/trezor/trezor-firmware/pull/4142
[#4151]: https://github.com/trezor/trezor-firmware/pull/4151
[#4155]: https://github.com/trezor/trezor-firmware/pull/4155
[#4160]: https://github.com/trezor/trezor-firmware/pull/4160
[#4161]: https://github.com/trezor/trezor-firmware/pull/4161
[#4165]: https://github.com/trezor/trezor-firmware/pull/4165
[#4167]: https://github.com/trezor/trezor-firmware/pull/4167
@ -1048,4 +1064,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4541]: https://github.com/trezor/trezor-firmware/pull/4541
[#4560]: https://github.com/trezor/trezor-firmware/pull/4560
[#4571]: https://github.com/trezor/trezor-firmware/pull/4571
[#1658739]: https://github.com/trezor/trezor-firmware/pull/1658739
[#4623]: https://github.com/trezor/trezor-firmware/pull/4623
[#4665]: https://github.com/trezor/trezor-firmware/pull/4665
[#4771]: https://github.com/trezor/trezor-firmware/pull/4771
[#4786]: https://github.com/trezor/trezor-firmware/pull/4786
[#4787]: https://github.com/trezor/trezor-firmware/pull/4787
[#4819]: https://github.com/trezor/trezor-firmware/pull/4819
[#4827]: https://github.com/trezor/trezor-firmware/pull/4827
[#4964]: https://github.com/trezor/trezor-firmware/pull/4964

View File

@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [2.8.10] (21st May 2025)
### Added
- Add Nostr support (in debug mode only!). [#4160]
- Visual cues to distinguish unlocked state on Homescreen. [#4964]
- Solana: rent fee calculation [#4933]
- Solana: loadable token definitions [#3541]
### Fixed
- Replaced "next page" icon with "..." ellipsis when confirming long message. [#4623]
- Updated EIP-1559 fee-related labels. [#4819]
- Allow firmware upgrade even if language change failed. [#4827]
- Solana: fees calculation is now exact [#4965]
## [2.8.9] (19th March 2025)
### Added
@ -1068,6 +1082,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4142]: https://github.com/trezor/trezor-firmware/pull/4142
[#4151]: https://github.com/trezor/trezor-firmware/pull/4151
[#4155]: https://github.com/trezor/trezor-firmware/pull/4155
[#4160]: https://github.com/trezor/trezor-firmware/pull/4160
[#4161]: https://github.com/trezor/trezor-firmware/pull/4161
[#4165]: https://github.com/trezor/trezor-firmware/pull/4165
[#4167]: https://github.com/trezor/trezor-firmware/pull/4167
@ -1092,4 +1107,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4541]: https://github.com/trezor/trezor-firmware/pull/4541
[#4560]: https://github.com/trezor/trezor-firmware/pull/4560
[#4571]: https://github.com/trezor/trezor-firmware/pull/4571
[#4623]: https://github.com/trezor/trezor-firmware/pull/4623
[#4665]: https://github.com/trezor/trezor-firmware/pull/4665
[#4771]: https://github.com/trezor/trezor-firmware/pull/4771
[#4786]: https://github.com/trezor/trezor-firmware/pull/4786
[#4787]: https://github.com/trezor/trezor-firmware/pull/4787
[#4819]: https://github.com/trezor/trezor-firmware/pull/4819
[#4827]: https://github.com/trezor/trezor-firmware/pull/4827
[#4964]: https://github.com/trezor/trezor-firmware/pull/4964

View File

@ -4,6 +4,24 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [2.8.10] (21st May 2025)
### Added
- [T3B1] Upgrade bundled bootloader to 2.1.10.
- Add Nostr support (in debug mode only!). [#4160]
- [T3T1] Visual cues to distinguish unlocked state on Homescreen. [#4964]
- Solana: rent fee calculation [#4933]
- Solana: loadable token definitions [#3541]
### Fixed
- Replaced "next page" icon with "..." ellipsis when confirming long message. [#4623]
- [T2T1] Fixed upgrade confirmation text overflow. [#4771]
- [T2T1] Fixed Solana staking dialog fonts. [#4786]
- [T2B1,T3B1] Fixed Solana staking dialog title. [#4787]
- Updated EIP-1559 fee-related labels. [#4819]
- Allow firmware upgrade even if language change failed. [#4827]
- Solana: fees calculation is now exact [#4965]
## [2.8.9] (19th March 2025)
### Added
@ -1097,6 +1115,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4142]: https://github.com/trezor/trezor-firmware/pull/4142
[#4151]: https://github.com/trezor/trezor-firmware/pull/4151
[#4155]: https://github.com/trezor/trezor-firmware/pull/4155
[#4160]: https://github.com/trezor/trezor-firmware/pull/4160
[#4161]: https://github.com/trezor/trezor-firmware/pull/4161
[#4165]: https://github.com/trezor/trezor-firmware/pull/4165
[#4167]: https://github.com/trezor/trezor-firmware/pull/4167
@ -1121,4 +1140,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4541]: https://github.com/trezor/trezor-firmware/pull/4541
[#4560]: https://github.com/trezor/trezor-firmware/pull/4560
[#4571]: https://github.com/trezor/trezor-firmware/pull/4571
[#4623]: https://github.com/trezor/trezor-firmware/pull/4623
[#4665]: https://github.com/trezor/trezor-firmware/pull/4665
[#4771]: https://github.com/trezor/trezor-firmware/pull/4771
[#4786]: https://github.com/trezor/trezor-firmware/pull/4786
[#4787]: https://github.com/trezor/trezor-firmware/pull/4787
[#4819]: https://github.com/trezor/trezor-firmware/pull/4819
[#4827]: https://github.com/trezor/trezor-firmware/pull/4827
[#4964]: https://github.com/trezor/trezor-firmware/pull/4964

View File

@ -4,9 +4,9 @@
// Auto-generated file, do not edit.
// clang-format off
// bootloader_T3B1.bin version 2.1.8.0
#define BOOTLOADER_T3B1_00 {0x23, 0x64, 0x01, 0x0c, 0x96, 0xc1, 0x04, 0x2f, 0x54, 0x12, 0x53, 0xb5, 0xd7, 0x23, 0xcf, 0xf9, 0x18, 0x59, 0xf1, 0xdd, 0x6a, 0x5e, 0x3a, 0x3f, 0xf2, 0xf1, 0x71, 0x55, 0xaf, 0x2e, 0x48, 0x92}
#define BOOTLOADER_T3B1_FF {0x8f, 0x63, 0x1a, 0x98, 0x56, 0x9c, 0xcc, 0xf1, 0xfc, 0x0b, 0x98, 0x62, 0x5d, 0xc6, 0xc7, 0x33, 0x73, 0x90, 0x2f, 0x69, 0x02, 0x57, 0xbd, 0x5e, 0x31, 0x4c, 0x0b, 0x5a, 0xdb, 0x01, 0x17, 0x24}
// bootloader_T3B1.bin version 2.1.10.0
#define BOOTLOADER_T3B1_00 {0x64, 0x7c, 0xac, 0x56, 0x1d, 0x10, 0xcb, 0x55, 0x78, 0x01, 0xce, 0x54, 0x85, 0xa0, 0xe7, 0x39, 0x08, 0x6f, 0xb9, 0xc2, 0x87, 0x35, 0x8b, 0x75, 0xa4, 0x7d, 0xdd, 0x7a, 0xd5, 0x10, 0xa7, 0x1f}
#define BOOTLOADER_T3B1_FF {0x49, 0xdd, 0x94, 0x60, 0xb7, 0xe9, 0x57, 0x6e, 0x7d, 0xb6, 0xd7, 0x63, 0x47, 0x04, 0xb4, 0x58, 0x3d, 0x47, 0x45, 0x57, 0xf3, 0x35, 0x69, 0x05, 0x8b, 0x84, 0x24, 0xdc, 0x81, 0x88, 0x80, 0x98}
// bootloader_T3B1_qa.bin version 2.1.7.0
#define BOOTLOADER_T3B1_QA_00 {0x2e, 0x90, 0x8a, 0x99, 0x25, 0x93, 0xcd, 0x9c, 0xf1, 0x23, 0x1e, 0x4e, 0x41, 0xfc, 0xc9, 0xf1, 0x4b, 0x06, 0x69, 0x57, 0x6e, 0x64, 0x84, 0x1c, 0xb1, 0xd9, 0x89, 0x0c, 0xa5, 0xb4, 0x38, 0xeb}

View File

@ -9,7 +9,7 @@ PUBLIC_KEYS = (
b"\xb8\xd2\xb2\x1d\xe2\x71\x24\xf0\x51\x1f\x90\x3a\xe7\xe6\x0e\x07\x96\x18\x10\xa0\xb8\xf2\x8e\xa7\x55\xfa\x50\x36\x7a\x8a\x2b\x8b",
)
MIN_DATA_VERSION = 1738953548
MIN_DATA_VERSION = 1741090563
FORMAT_VERSION = b"trzd1"
if __debug__:

View File

@ -5,6 +5,13 @@
"commit": "be096b28adbe7c354dd502167c52e09be81140e2"
},
"history": [
{
"signature": "0309f4f95fa152310e8a984e3b105cd899d12e37a7510057f37f20a72955635e0ff1605da8c44a847c86f8b0aa0afada995f0c628234fa910d0aa275fbaef8f504",
"version": "2.8.10.0",
"merkle_root": "cf835159e227117eb1c2cd8a784c259b523c5b9489e408a4cefa169601437af6",
"datetime": "2025-05-12T07:36:20.997218",
"commit": "2a65d18200580005dc419b9569ed97fae440806a"
},
{
"signature": "03a0f2df5f468356b0444a24050a60789bff459a90328533b0aa9693666ca3145c8df72adc23f5b7a52d0814ef58c44ebec0b4f4482d12fa137b6c9a8858374209",
"version": "2.8.9.0",

View File

@ -1 +0,0 @@
Clear sign ETH staking transactions on Everstake pool.

View File

@ -1 +0,0 @@
Use `GWei` when formatting large ETH amounts.

View File

@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 1.13.1 [21st May 2025]
### Added
- Clear sign ETH staking transactions on Everstake pool. [#4851]
- Entropy check workflow in ResetDevice.
### Fixed
- Use `GWei` when formatting large ETH amounts. [#4932]
## 1.13.0 [19th February 2025]
### Added
@ -640,3 +649,5 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#4119]: https://github.com/trezor/trezor-firmware/pull/4119
[#4324]: https://github.com/trezor/trezor-firmware/pull/4324
[#4396]: https://github.com/trezor/trezor-firmware/pull/4396
[#4851]: https://github.com/trezor/trezor-firmware/pull/4851
[#4932]: https://github.com/trezor/trezor-firmware/pull/4932

View File

@ -229,20 +229,33 @@ static const CoinInfo *fsm_getCoin(bool has_name, const char *name) {
return coin;
}
static HDNode *fsm_getDerivedNode(const char *curve, const uint32_t *address_n,
size_t address_n_count,
uint32_t *fingerprint) {
static HDNode *fsm_getDerivedNodeEx(const char *curve,
const uint32_t *address_n,
size_t address_n_count, const uint8_t *seed,
uint32_t *fingerprint) {
static CONFIDENTIAL HDNode node;
if (fingerprint) {
*fingerprint = 0;
}
if (!config_getRootNode(&node, curve)) {
layoutHome();
return 0;
if (seed == NULL) {
if (!config_getRootNode(&node, curve)) {
layoutHome();
return 0;
}
} else {
if (hdnode_from_seed(seed, 64, curve, &node) != 1) {
fsm_sendFailure(FailureType_Failure_NotInitialized,
_("Unsupported curve"));
layoutHome();
return 0;
}
}
if (!address_n || address_n_count == 0) {
return &node;
}
if (hdnode_private_ckd_cached(&node, address_n, address_n_count,
fingerprint) == 0) {
fsm_sendFailure(FailureType_Failure_ProcessError,
@ -253,6 +266,13 @@ static HDNode *fsm_getDerivedNode(const char *curve, const uint32_t *address_n,
return &node;
}
static HDNode *fsm_getDerivedNode(const char *curve, const uint32_t *address_n,
size_t address_n_count,
uint32_t *fingerprint) {
return fsm_getDerivedNodeEx(curve, address_n, address_n_count, NULL,
fingerprint);
}
static bool fsm_getSlip21Key(const char *path[], size_t path_count,
uint8_t key[32]) {
const uint8_t *seed = config_getSeed();
@ -413,6 +433,7 @@ void fsm_msgRebootToBootloader(void) {
}
void fsm_abortWorkflows(void) {
reset_abort();
recovery_abort();
signing_abort();
authorization_type = 0;

View File

@ -64,6 +64,7 @@ void fsm_msgLoadDevice(const LoadDevice *msg);
#endif
void fsm_msgResetDevice(const ResetDevice *msg);
void fsm_msgEntropyAck(const EntropyAck *msg);
void fsm_msgEntropyCheckContinue(const EntropyCheckContinue *msg);
void fsm_msgBackupDevice(const BackupDevice *msg);
void fsm_msgCancel(const Cancel *msg);
void fsm_msgLockDevice(const LockDevice *msg);

View File

@ -20,10 +20,15 @@
void fsm_msgGetPublicKey(const GetPublicKey *msg) {
RESP_INIT(PublicKey);
CHECK_INITIALIZED
CHECK_PIN
// Get temporary seed if running entropy check, otherwise ensure the device is
// initialized.
const uint8_t *seed = reset_get_seed();
if (seed == NULL) {
CHECK_INITIALIZED
}
InputScriptType script_type =
msg->has_script_type ? msg->script_type : InputScriptType_SPENDADDRESS;
@ -50,15 +55,23 @@ void fsm_msgGetPublicKey(const GetPublicKey *msg) {
}
}
// Make sure we never display the temporary XPUB to the user.
if (seed != NULL && msg->show_display) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Showing temporary XPUB is forbidden"));
layoutHome();
return;
}
// derive m/0' to obtain root_fingerprint
uint32_t root_fingerprint;
uint32_t path[1] = {PATH_HARDENED | 0};
HDNode *node = fsm_getDerivedNode(curve, path, 1, &root_fingerprint);
HDNode *node = fsm_getDerivedNodeEx(curve, path, 1, seed, &root_fingerprint);
if (!node) return;
uint32_t fingerprint;
node = fsm_getDerivedNode(curve, msg->address_n, msg->address_n_count,
&fingerprint);
node = fsm_getDerivedNodeEx(curve, msg->address_n, msg->address_n_count, seed,
&fingerprint);
if (!node) return;
if (hdnode_fill_public_key(node) != 0) {
@ -132,7 +145,11 @@ void fsm_msgGetPublicKey(const GetPublicKey *msg) {
resp->root_fingerprint = root_fingerprint;
msg_write(MessageType_MessageType_PublicKey, resp);
layoutHome();
// Keep screen layout when running entropy check.
if (seed == NULL) {
layoutHome();
}
}
static PathSchema fsm_getUnlockedSchema(MessageType message_type) {

View File

@ -321,6 +321,8 @@ void fsm_msgResetDevice(const ResetDevice *msg) {
msg->strength == 192 || msg->strength == 256,
_("Invalid seed strength"));
fsm_abortWorkflows();
reset_init(msg->has_strength ? msg->strength : 128,
msg->has_passphrase_protection && msg->passphrase_protection,
msg->has_pin_protection && msg->pin_protection,
@ -328,13 +330,18 @@ void fsm_msgResetDevice(const ResetDevice *msg) {
msg->has_label ? msg->label : 0,
msg->has_u2f_counter ? msg->u2f_counter : 0,
msg->has_skip_backup ? msg->skip_backup : false,
msg->has_no_backup ? msg->no_backup : false);
msg->has_no_backup ? msg->no_backup : false,
msg->has_entropy_check ? msg->entropy_check : false);
}
void fsm_msgEntropyAck(const EntropyAck *msg) {
reset_entropy(msg->entropy.bytes, msg->entropy.size);
}
void fsm_msgEntropyCheckContinue(const EntropyCheckContinue *msg) {
reset_continue(msg->has_finish ? msg->finish : false);
}
void fsm_msgBackupDevice(const BackupDevice *msg) {
(void)msg;
@ -497,6 +504,8 @@ void fsm_msgRecoveryDevice(const RecoveryDevice *msg) {
msg->type == RecoveryType_DryRun,
_("UnlockRepeatedBackup not supported"))
fsm_abortWorkflows();
const bool dry_run = msg->has_type ? msg->type == RecoveryType_DryRun : false;
if (!dry_run) {
CHECK_NOT_INITIALIZED

View File

@ -11,7 +11,7 @@ SKIPPED_MESSAGES := Cardano DebugMonero Eos Monero Ontology Ripple SdProtect Tez
UnlockBootloader AuthenticateDevice AuthenticityProof \
Solana StellarClaimClaimableBalanceOp \
ChangeLanguage DataChunkRequest DataChunkAck \
SetBrightness DebugLinkOptigaSetSecMax EntropyCheckReady EntropyCheckContinue \
SetBrightness DebugLinkOptigaSetSecMax \
BenchmarkListNames BenchmarkRun BenchmarkNames BenchmarkResult \
NostrGetPubkey NostrPubkey NostrSignEvent NostrEventSignature \
BleUnpair

View File

@ -30,8 +30,8 @@ BackupDevice.groups type:FT_IGNORE
Entropy.entropy max_size:1024
EntropyRequest.entropy_commitment type:FT_IGNORE
EntropyRequest.prev_entropy type:FT_IGNORE
EntropyRequest.entropy_commitment max_size:32
EntropyRequest.prev_entropy max_size:32
EntropyAck.entropy max_size:128

View File

@ -22,6 +22,7 @@
#include "config.h"
#include "fsm.h"
#include "gettext.h"
#include "hmac.h"
#include "layout2.h"
#include "memzero.h"
#include "messages.h"
@ -34,18 +35,37 @@
static uint32_t strength;
static uint8_t int_entropy[32];
static bool awaiting_entropy = false;
static uint8_t seed[64];
static const char *reset_mnemonic;
static bool skip_backup = false;
static bool no_backup = false;
static bool entropy_check = false;
static enum {
RESET_NONE = 0,
RESET_ENTROPY_REQUEST,
RESET_ENTROPY_CHECK_READY,
} reset_state = RESET_NONE;
static void send_entropy_request(bool set_prev_entropy);
static void reset_finish(void);
static void entropy_check_progress(uint32_t iter, uint32_t total) {
(void)iter;
(void)total;
layoutProgress(_("Entropy check"), 0);
}
void reset_init(uint32_t _strength, bool passphrase_protection,
bool pin_protection, const char *language, const char *label,
uint32_t u2f_counter, bool _skip_backup, bool _no_backup) {
uint32_t u2f_counter, bool _skip_backup, bool _no_backup,
bool _entropy_check) {
if (_strength != 128 && _strength != 192 && _strength != 256) return;
strength = _strength;
skip_backup = _skip_backup;
no_backup = _no_backup;
entropy_check = _entropy_check;
layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL,
_("Do you really want to"), _("create a new wallet?"), NULL,
@ -56,8 +76,6 @@ void reset_init(uint32_t _strength, bool passphrase_protection,
return;
}
random_buffer(int_entropy, 32);
if (pin_protection && !protectChangePin(false)) {
layoutHome();
return;
@ -67,36 +85,79 @@ void reset_init(uint32_t _strength, bool passphrase_protection,
config_setLanguage(language);
config_setLabel(label);
config_setU2FCounter(u2f_counter);
send_entropy_request(false);
}
static void send_entropy_request(bool set_prev_entropy) {
EntropyRequest resp = {0};
memzero(&resp, sizeof(EntropyRequest));
if (set_prev_entropy) {
memcpy(resp.prev_entropy.bytes, int_entropy, sizeof(int_entropy));
resp.prev_entropy.size = sizeof(int_entropy);
resp.has_prev_entropy = true;
}
random_buffer(int_entropy, sizeof(int_entropy));
if (entropy_check) {
hmac_sha256(int_entropy, sizeof(int_entropy), NULL, 0,
resp.entropy_commitment.bytes);
resp.entropy_commitment.size = SHA256_DIGEST_LENGTH;
resp.has_entropy_commitment = true;
}
msg_write(MessageType_MessageType_EntropyRequest, &resp);
awaiting_entropy = true;
reset_state = RESET_ENTROPY_REQUEST;
}
void reset_entropy(const uint8_t *ext_entropy, uint32_t len) {
if (!awaiting_entropy) {
if (reset_state != RESET_ENTROPY_REQUEST) {
fsm_sendFailure(FailureType_Failure_UnexpectedMessage,
_("Not in Reset mode"));
_("Entropy not requested"));
return;
}
awaiting_entropy = false;
uint8_t secret[SHA256_DIGEST_LENGTH] = {0};
SHA256_CTX ctx = {0};
sha256_Init(&ctx);
SHA256_UPDATE_BYTES(&ctx, int_entropy, 32);
sha256_Update(&ctx, ext_entropy, len);
sha256_Final(&ctx, int_entropy);
const char *mnemonic = mnemonic_from_data(int_entropy, strength / 8);
memzero(int_entropy, 32);
sha256_Final(&ctx, secret);
reset_mnemonic = mnemonic_from_data(secret, strength / 8);
memzero(secret, sizeof(secret));
if (!entropy_check) {
reset_finish();
return;
}
reset_state = RESET_ENTROPY_CHECK_READY;
mnemonic_to_seed(reset_mnemonic, "", seed, entropy_check_progress);
EntropyCheckReady resp = {0};
msg_write(MessageType_MessageType_EntropyCheckReady, &resp);
}
void reset_continue(bool finish) {
if (reset_state != RESET_ENTROPY_CHECK_READY) {
fsm_sendFailure(FailureType_Failure_UnexpectedMessage,
_("Entropy check not ready"));
return;
}
if (finish) {
reset_finish();
} else {
send_entropy_request(true);
}
}
static void reset_finish(void) {
memzero(int_entropy, sizeof(int_entropy));
memzero(seed, sizeof(seed));
reset_state = RESET_NONE;
if (skip_backup || no_backup) {
if (no_backup) {
config_setNoBackup();
} else {
config_setNeedsBackup(true);
}
if (config_setMnemonic(mnemonic)) {
if (config_setMnemonic(reset_mnemonic)) {
fsm_sendSuccess(_("Device successfully initialized"));
} else {
fsm_sendFailure(FailureType_Failure_ProcessError,
@ -104,11 +165,18 @@ void reset_entropy(const uint8_t *ext_entropy, uint32_t len) {
}
layoutHome();
} else {
reset_backup(false, mnemonic);
reset_backup(false, reset_mnemonic);
}
mnemonic_clear();
}
const uint8_t *reset_get_seed(void) {
if (reset_state != RESET_ENTROPY_CHECK_READY) {
return NULL;
}
return seed;
}
static char current_word[10];
// separated == true if called as a separate workflow via BackupMessage
@ -170,6 +238,16 @@ void reset_backup(bool separated, const char *mnemonic) {
layoutHome();
}
void reset_abort(void) {
memzero(int_entropy, sizeof(int_entropy));
memzero(seed, sizeof(seed));
mnemonic_clear();
if (reset_state != RESET_NONE) {
reset_state = RESET_NONE;
layoutHome();
}
}
#if DEBUG_LINK
uint32_t reset_get_int_entropy(uint8_t *entropy) {

View File

@ -25,10 +25,14 @@
void reset_init(uint32_t _strength, bool passphrase_protection,
bool pin_protection, const char *language, const char *label,
uint32_t u2f_counter, bool _skip_backup, bool _no_backup);
uint32_t u2f_counter, bool _skip_backup, bool _no_backup,
bool _entropy_check);
void reset_entropy(const uint8_t *ext_entropy, uint32_t len);
void reset_continue(bool finish);
const uint8_t *reset_get_seed(void);
void reset_backup(bool separated, const char *mnemonic);
uint32_t reset_get_int_entropy(uint8_t *entropy);
const char *reset_get_word(void);
void reset_abort(void);
#endif

View File

@ -14,14 +14,23 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from typing import Generator
import pytest
from mnemonic import Mnemonic
from slip10 import SLIP10
from trezorlib import device, messages
from trezorlib.btc import get_public_node
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.tools import parse_path
from ...common import EXTERNAL_ENTROPY, generate_entropy
from ...common import (
EXTERNAL_ENTROPY,
MOCK_GET_ENTROPY,
BRGeneratorType,
generate_entropy,
)
pytestmark = pytest.mark.models("legacy")
@ -216,3 +225,130 @@ def test_already_initialized(client: Client):
pin_protection=True,
label="label",
)
class Bip39InputFlow:
def __init__(self, client: Client):
self.client = client
self.mnemonic = None
def _get_mnemonic(
self, strength: int
) -> Generator[None, messages.ButtonRequest, list[str]]:
mnemonic: list[str] = []
for _ in range(strength // 32 * 3):
br = yield
assert br.code == messages.ButtonRequestType.ConfirmWord
mnemonic.append(self.client.debug.read_reset_word())
self.client.debug.press_yes()
return mnemonic
def input_flow_bip39_reset_backup(self, strength: int) -> BRGeneratorType:
# 1. Confirm Reset
br = yield
assert br.code == messages.ButtonRequestType.ProtectCall
self.client.debug.press_yes()
mnemonic_write = yield from self._get_mnemonic(strength)
mnemonic_check = yield from self._get_mnemonic(strength)
assert mnemonic_write == mnemonic_check
self.mnemonic = " ".join(mnemonic_write)
@pytest.mark.setup_client(uninitialized=True)
def test_reset_entropy_check(client: Client):
strength = 256 # 24 words
with client:
IF = Bip39InputFlow(client)
client.set_input_flow(IF.input_flow_bip39_reset_backup(strength))
# No PIN, no passphrase
path_xpubs = device.setup(
client,
strength=strength,
passphrase_protection=False,
pin_protection=False,
label="test",
entropy_check_count=2,
backup_type=messages.BackupType.Bip39,
_get_entropy=MOCK_GET_ENTROPY,
)
# Check that the displayed mnemonic is identical to the stored one.
assert IF.mnemonic.encode("utf-8") == client.debug.state().mnemonic_secret
# Check that the device is properly initialized.
assert client.features.initialized is True
assert (
client.features.backup_availability == messages.BackupAvailability.NotAvailable
)
assert client.features.pin_protection is False
assert client.features.passphrase_protection is False
seed = Mnemonic.to_seed(IF.mnemonic, passphrase="")
slip10 = SLIP10.from_seed(seed)
for path, xpub in path_xpubs:
# Check that the device returns the same XPUBs as those from the entropy check.
res = get_public_node(client, path)
assert res.xpub == xpub
# Check that the XPUBs derived from the displayed mnemonic are the same as those
# from the entropy check.
assert slip10.get_xpub_from_path(path) == xpub
@pytest.mark.setup_client(uninitialized=True)
def test_entropy_check(client: Client):
with client:
client.set_expected_responses(
[
messages.ButtonRequest(code=messages.ButtonRequestType.ProtectCall),
messages.EntropyRequest,
messages.EntropyCheckReady,
messages.PublicKey,
messages.PublicKey,
messages.EntropyRequest,
messages.EntropyCheckReady,
messages.PublicKey,
messages.PublicKey,
messages.EntropyRequest,
messages.EntropyCheckReady,
messages.PublicKey,
messages.PublicKey,
messages.Success,
messages.Features,
]
)
device.setup(
client,
strength=256,
entropy_check_count=2,
backup_type=messages.BackupType.Bip39,
skip_backup=True,
pin_protection=False,
passphrase_protection=False,
_get_entropy=MOCK_GET_ENTROPY,
)
@pytest.mark.setup_client(uninitialized=True)
def test_no_entropy_check(client: Client):
with client:
client.set_expected_responses(
[
messages.ButtonRequest(code=messages.ButtonRequestType.ProtectCall),
messages.EntropyRequest,
messages.Success,
messages.Features,
]
)
device.setup(
client,
strength=256,
entropy_check_count=0,
backup_type=messages.BackupType.Bip39,
skip_backup=True,
pin_protection=False,
passphrase_protection=False,
_get_entropy=MOCK_GET_ENTROPY,
)

View File

@ -602,10 +602,13 @@
"T1B1_en_reset_recovery-test_reset_bip39_skipbackup.py::test_reset_device_skip_backup": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"T1B1_en_reset_recovery-test_reset_bip39_skipbackup.py::test_reset_device_skip_backup_break": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"T1B1_en_reset_recovery-test_reset_bip39_t1.py::test_already_initialized": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"T1B1_en_reset_recovery-test_reset_bip39_t1.py::test_entropy_check": "b63a40ea5f6d8c59a2b54db8f5f01d0aaa4b0dea7c91ddd1bd40489720ae729c",
"T1B1_en_reset_recovery-test_reset_bip39_t1.py::test_failed_pin": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"T1B1_en_reset_recovery-test_reset_bip39_t1.py::test_no_entropy_check": "b63a40ea5f6d8c59a2b54db8f5f01d0aaa4b0dea7c91ddd1bd40489720ae729c",
"T1B1_en_reset_recovery-test_reset_bip39_t1.py::test_reset_device_128": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"T1B1_en_reset_recovery-test_reset_bip39_t1.py::test_reset_device_192": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"T1B1_en_reset_recovery-test_reset_bip39_t1.py::test_reset_device_256_pin": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"T1B1_en_reset_recovery-test_reset_bip39_t1.py::test_reset_entropy_check": "d18e5ebf3a318a04935cbf1c1d2a9591ad209d352baed8d93aa4398b87c0bc72",
"T1B1_en_stellar-test_stellar.py::test_get_address[parameters0-result0]": "b004cb1a815072ae3ba9f4aadeeb9d37d3309513e973f7ddeb2ee23a056db726",
"T1B1_en_stellar-test_stellar.py::test_get_address[parameters1-result1]": "101692e06782269486e3f1093fdf03200e0cdce4b4ffc7cc5fc779b80f69d1fc",
"T1B1_en_stellar-test_stellar.py::test_get_address[parameters2-result2]": "508bbd5285d2f3087fa3b872ff053a286630b80beacd0b8b30c8577aa5396c86",
@ -709,7 +712,7 @@
"T1B1_en_test_msg_loaddevice.py::test_load_device_2": "f89f8fcecf250b76dcca3e52a5a678e14ca5eeae105fa59848db41ab514d6614",
"T1B1_en_test_msg_loaddevice.py::test_load_device_utf": "9523984b9cd124422558fe14ae20aab35338f86f08756d11919db7b2d3b86781",
"T1B1_en_test_msg_ping.py::test_ping": "de7fc40b2f35e82fa486f1b97ee3e34a96d0a67412537e8a0fddacc0b0b1649d",
"T1B1_en_test_msg_wipedevice.py::test_autolock_not_retained": "7f5d22cc7797ce4ca6d9f46f633918aba527972c8d683493e95da45503486f61",
"T1B1_en_test_msg_wipedevice.py::test_autolock_not_retained": "9ab4e01aaf78d4ffeaadf43883258fd2ded7d4f7ebbdba9c70bd60baad314860",
"T1B1_en_test_msg_wipedevice.py::test_wipe_device": "aac15a6d12d21966c77572aeebd56ebc2a47ecba3a508f5a421af2a5da2919e7",
"T1B1_en_test_pin.py::test_correct_pin": "31e4ef1ef1f40b58c66bcde7631fe12699321dcdfc144381ac2b3e5668d0de5c",
"T1B1_en_test_pin.py::test_exponential_backoff_t1": "427faf2049e9998229e0d40c9b54f2e359a7d2df2ba129187dafc7d2f2cc9986",