This Wednesday we are releasing the firmware update 1.9.0 for Trezor One devices and firmware update 2.3.0 for Trezor Model T devices. This post describes the new features and security fixes brought by these updates.

New Features

Passphrase Redesign + Session Caching

Passphrase is an important part of the whole Trezor ecosystem. In these firmware updates we have overhauled the design and made many internal improvements and two major user-facing changes.

First, on both of our device models, we are introducing passphrase caching. Up until now, if you used multiple passphrases, you had to enter the passphrase again every time you switched to a different passphrase-protected wallet. Depending on the usage, Trezor is now capable of caching up to 10 passphrases at the same time. This does not concern the Wallet at the moment because it requires Trezor to be reconnected to change the passphrase. However this is ready for the next generation of our wallet, which is coming soon. Stay tuned!

Second, on Trezor Model T, the decision whether the passphrase will be entered on the device is prompted directly in the Wallet (see picture below). This helps the overall UX since the user’s focus stays in the Wallet until the passphrase needs to be entered on the device. On the other hand, if you like to be asked for the passphrase on the device every time, you can use

trezorctl set passphrase enabled --force-on-device to enforce that.

Wipe Code

The wipe code functions as a “self-destruct PIN”. If the wipe code is ever entered into any PIN entry dialog, then all private data will be immediately erased from your Trezor and the device will be reset to factory defaults. You can write the wipe code somewhere near your Trezor as a decoy PIN, so that if someone tries to unlock the device without your consent, they will cause it to wipe itself.

To enable this feature you will need trezorctl version 0.11.6 or later. The command to set or change the wipe code is: trezorctl set wipe-code

Note that when changing the wipe code you first need to enter your PIN. Trezor never asks for the old wipe code, so if you accidentally enter it, the device will get wiped!

To disable the wipe code feature use: trezorctl set wipe-code -r

MultiSig: Show XPUBs

While showing a multisig address on the Trezor device, a user can also show individual XPUBs which are involved and confirm that the address is correct.

Ed25519 in FIDO2

Two-factor authentication (2FA) standards supported by Trezor (U2F and FIDO2) use ECDSA signatures with the NISP P-256 curve by default. But for those of you who strive to use state of the art cryptography to secure your logins, Trezor Model T now supports Ed25519 signatures in FIDO2. You will mainly appreciate this if you use OpenSSH with FIDO2.

SD card protection

This feature serves as additional protection against physical attacks on the Trezor Model T. When it is enabled, a randomly generated secret is stored on the microSD card that you can insert into your Trezor Model T. During every PIN checking and unlocking operation this secret is combined with the entered PIN value to decrypt data stored on the device. Simply put, the device gets bound to the SD card and cannot be unlocked without it until you intentionally disable the feature or factory-reset your Trezor. Thus if you are concerned about physical attacks, you can remove the SD card whenever the device is not in use and keep the two in separate locations. One without the other is worthless to an attacker, because the SD card secret is an entirely random value which carries no information about your seed or passphrase.

To enable this feature you will need trezorctl version 0.11.6 or later and a FAT32 formatted microSD card. If the card is not properly formatted, then Trezor will offer to erase and format the card for you. There are three commands related to SD protect:

trezorctl device sd-protect enable

trezorctl device sd-protect disable

trezorctl device sd-protect refresh

The refresh command replaces the current SD card secret with a new one. This is useful if you inserted the SD card into a malware-infected computer and are worried that the secret stored on the card may have been compromised.

Security Fixes

This round of updates also brings five fixes to security vulnerabilities. Four of them were reported by a long-time contributor to Trezor: Saleem Rashid, while the last one was reported by Sebastian Kung. We’d like to applaud both security specialists for their outstanding work and for disclosing their findings via our responsible disclosure program. Thank you!

OP_RETURN treated as change output

This vulnerability was present only on the Trezor Model T.

OP_RETURN is a special script opcode in Bitcoin, which allows adding arbitrary data to the transaction in the blockchain. OP_RETURN outputs have no destination and these outputs are unspendable.

Consider a transaction with two outputs, one of which is OP_RETURN and the other one is a change output. By “change output” we mean an output constructed from the user’s seed defined by the path sent in the address_n field. This field has no meaning for OP_RETURN since it does not have any destination or an address.

Nevertheless, when this field was sent for an OP_RETURN output into Trezor, equal to the other output’s address_n , then Trezor evaluated the OP_RETURN as a change output. Since change outputs do not require confirmation on Trezor, the confirmation dialog for the OP_RETURN output wasn’t displayed. Fortunately, Trezor checks that the amount is equal to 0 for every OP_RETURN output so it wasn’t possible to burn any coins. However, this is still a bug, because some applications build on top of the Bitcoin blockchain using the OP_RETURN (such as the Omni layer).

How was the vulnerability fixed?

Trezor now strictly validates all transaction outputs before signing. For OP_RETURN, an error is raised if some unexpected fields are provided. We also make sure an output is only marked as a change-output if the script type matches the correct subset.

Malicious change in mixed transactions

This vulnerability was present only on the Trezor Model T.

In order to be able to sign large transactions with many inputs or outputs, we came up with a technique called streamed signing. This process has two main phases. In the first phase all inputs are sent to the wallet to determine the amount being spent and all outputs are sent to be confirmed one by one on the wallet’s screen by the user. There is one exception, a change-output does not require user confirmation, because the funds going into this output remain in the user’s possession. In the second phase, all inputs are again sent to the wallet to be signed one by one, while checking that nothing has changed.

A multisig address can also serve as a change-output, but only if all inputs come from that same multisig address. It was possible to claim in the first phase that an input comes from some multisig address, when in fact it did not. This vulnerability would allow a malware-infected computer to mislead Trezor Model T into incorrectly identifying a multisig output as a change-output. The malware would thus be able to provide a 1-of-2 multisig output which would not require user confirmation. The two multisig participants of this output would be the user and the attacker, either of which could then spend this output, leading to possible theft of user funds.

How was the vulnerability fixed?

The cause of this vulnerability was that Trezor Model T did not properly verify that the information provided about the inputs was the same in both phases. In the second phase an additional verification step was added to ensure that if all inputs in the first phase had the same multisig address, then they all still have that same address in the second phase.

Insufficient field size check in Protobuf

This vulnerability was present only on the Trezor Model T.

Trezor communicates with the host computer via Protobuf-encoded messages. Each message consists of several fields, and each field can contain a number, text, sequence of bytes, or a sub-message. Notably, however, Protobuf does not place any restrictions on the length of the field. When you receive a message with a bytes field, it can be one byte, zero bytes, or 4 000 000 bytes.

Each Bitcoin transaction input is sent to Trezor as a protobuf message, which contains the previous transaction hash (or prevhash) encoded as bytes. The prevhash must always be exactly 32 bytes long, but Trezor Model T would accept a prevhash of any length.

Due to that, malware might craft a transaction that could be interpreted in two different ways: first, a legitimate transaction which unknowingly contains a very long prevhash; and second, hidden in the long prevhash is an output sending all funds to the attacker’s address. The first version would be sent to Trezor in the first phase, where the user is asked to confirm the outputs. The second version would be sent in the second phase, where signatures are generated.

Fortunately, due to unrelated limitations, the resulting transaction would be non-standard and would not be propagated by the Bitcoin network. An attacker wanting to spend this transaction would have to mine their own block.

How was the vulnerability fixed?

A check was added that rejects transaction hashes sent from the computer if they are not exactly 32 bytes long. In addition, the field length is double-checked when generating the binary representation of a transaction.

Inconsistent sanitization of transaction inputs

Similarly to the other attacks described above some fields were not sanitized properly. In this case, an attacker might have created a special transaction consisting of a traditional (single signature) input and a multisig output. The attacker composed the multisig part of the output as a 1 of 2 multisig, where one of the participants was the victim and the other one was the attacker. When the multisig field was sent for the input as well (although marked as a single signature) Trezor incorrectly concluded the output is a change-output.

How was the vulnerability fixed?

The inputs and outputs are now thoroughly validated on arrival.

Monero unlock_time issue

This vulnerability was present only on the Trezor Model T.

The Monero field unlock_time was not confirmed on the device’s display. Since the Monero network does not do any sanity checks for this field, this allows a perpetrator to lock user’s funds for a very long time by simply setting it to a very high value.

How was the vulnerability fixed?

We fixed the issue by showing the contents of the unlock_time field on the device’s display if it is set to a non-standard (non-zero) value.

Summary and the key takeaway

In this round of firmware updates we introduced several new features (such as Wipe Code and SD card protection) and fixed five security issues. At the time of writing this article, there is no evidence that any of these vulnerabilities have ever been exploited. As always, we strongly recommend keeping all Trezor devices updated with the latest firmware to maintain the maximum level of security.

How can I update my Trezor?

You will find the step-by-step instructions in our User manual. Before you start, make sure to have your recovery seed ready at hand.

Please note that if your Trezor One device is currently running firmware version 1.6.1 (bootloader version 1.4.0), your device memory will be wiped after this update. Please make sure you have the correct recovery seed with you, as you will need to recover your Trezor device from seed backup. You can test your recovery seed before you update the device firmware.

Timeline