We use [Protobuf v2](https://developers.google.com/protocol-buffers/) for host-device communication. The communication cycle is very simple, Trezor receives a message, acts on it and responds with another message. Trezor on its own is incapable of initiating the communication.
The Protobuf definitions can be found in `common/protob`.
_Note: In this section we describe the internal functioning of the communication protocol. If you wish to implement Trezor support you should use [Connect](https://github.com/trezor/connect/) or [python-trezor](https://pypi.org/project/trezor/), which will do all this hard work for you._
We use [Protobuf v2](https://developers.google.com/protocol-buffers/) for host-device communication. The communication cycle is very simple, Trezor receives a message (request), acts on it and responds with another one (response). Trezor on its own is incapable of initiating the communication.
## Definitions
Protobuf messages are defined in the [Common](https://github.com/trezor/trezor-firmware/tree/master/common) project, which is part of this monorepo. This repository is also exported to [trezor/trezor-common](https://github.com/trezor/trezor-common) to be used by third parties, which prefer not to include the whole monorepo. That copy is read-only mirror and all changes are happening in this monorepo.
As of \[versions TBD\] we have changed how [passphrase](https://wiki.trezor.io/Passphrase) is communicated between the Host and the Device.
Passphrase is very tightly coupled with _sessions_. The reader is encouraged to read on that topic first in the [sessions.md](sessions.md) section.
## Scheme
As soon as Trezor needs the passphrase to do BIP-39/SLIP-39 derivations it prompts the user for passphrase.
```
GetAddress(...)
---------> PassphraseRequest()
<---------
PassphraseAck
(str passphrase, bool on_device)
---------> Address(...)
<---------
```
In the default Trezor setting, the passphrase is obtained from the Host. Trezor sends a PassphraseRequest message and awaits PassphraseAck as a response. This message contains field `passphrase` to transmit it or it has `on_device` boolean flag to indicate that the user wishes to enter the passphrase on Trezor instead. Setting both `passphrase` and `on_device` to true is forbidden.
Note that this has changed as of TBD. In previous firmware versions the `on_device` flag was in the PassphraseRequest message, since this decision has been made on Trezor. We also had two additional messages PassphraseStateRequest and PassphraseStateAck which were removed.
## Example
On an initialized device with passphrase enabled a common communication starts like this:
```
Initialize()
---------> Features(..., session_id)
<---------
GetAddress(...)
---------> PassphraseRequest()
<---------
PassphraseAck(...)
---------> Address(...)
<---------
```
The device requested the passphrase since the BIP-39/SLIP-39 seed is not yet cached. After this workflow the seed is cached and the passphrase will therefore never be requested again unless the session is cleared*.
Since we do not have sessions, the Host can not be sure that someone else has not used the device and applied another session id (e.g. changed the Passphrase). To work around this we send the session id again on every subsequent message. See more on that in [session.md]().
```
Initialize(session_id)
---------> Features(..., session_id)
<---------
GetPublicKey(...)
---------> PublicKey(...)
<---------
```
As long as the session_id in `Initialize` is the same as the one Trezor stores internally, Trezor guarantees the same passphrase is being used.
----
\* There is one exception and that is Cardano. Because Cardano has a different BIP-39/SLIP-39 derivation scheme for passphrase we can not use the cached seed. As a workaround we prompt for the passphrase again in such case and cache the cardano seed in the cardano app directly.
## Passphrase always on device
User might want to enforce the passphrase entry on the device every time without the hassle of instructing the Host to do so.
For such cases the user may apply the *Passphrase always on device* setting. As the name suggests, with this setting the passphrase is prompted on the device right away and no PassphraseRequest/PassphraseAck messages are exchanged. Note that the passphrase is prompted only once for given session id. If the user wishes to enter another passphrase they need to either send Initialize(session_id=None) or replug the device.
Currently the communication protocol lacks sessions, which are planned to be introduced in the near future (see [#79](https://github.com/trezor/trezor-firmware/issues/79)).
To ensure the device is in the expected state we use something called _session_id_. Session id is a 32 bytes long random blob which identifies the internal device state (mainly its caches). This is primarily useful for passphrase to make sure the same passphrase is cached in the device as the one the user entered a few minutes ago. See [passphrase.md](passphrase.md) for more on that.
On first initialization the Host does not have a session id and starts the communication with an empty Initialize:
```
Initialize()
---------> Features(..., session_id)
<---------
```
After the first Features message is received the Host might store the session_id. To ensure the device state Host must send the Initialize message again including that particular session_id:
```
Initialize(session_id)
---------> Features(..., session_id)
<---------
Request
---------> Response
<---------
```
So to make sure the device state has not changed, the Host must send the Initialize message with the correctly stored session_id before each request. Yes, this is stupid.
As mentioned, sessions will be introduced soon™ and fix that. We will probably take the first few bytes of the session_id, declare it a session id, and the rest will remain, without the annoying requirement of sending Initialize before every message.
----
The session is terminated and therefore the caches are cleared if:
- Initialize.session_id is empty.
- Initialize.session_id is different then the one cached in Trezor.
- Trezor is replugged (session is not persistent).
@ -6,13 +6,38 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
_At the moment, the project does **not** adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). That is expected to change with version 1.0._
_At the moment, the project does **not** adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). That is expected to change with version 1.0._
## [0.11.7] - Unreleased
## [0.12.0] - Unreleased
### Added
### Added
- support for firmwares 1.9.0 and 2.3.0
- Model T now defaults to entering passphrase on device. New trezorctl option `-P`
enforces entering passphrase on host.
- support for "passphrase always on device" mode on model T
- new trezorctl command `get-session` and option `-s` allows entering passphrase once
for multiple subsequent trezorctl operations
- built-in functionality of UdpTransport to wait until an emulator comes up, and the
- built-in functionality of UdpTransport to wait until an emulator comes up, and the
related command `trezorctl wait-for-emulator`
related command `trezorctl wait-for-emulator`
### Changed
- API for `cosi` module was streamlined: `verify_m_of_n` is now `verify`, the old
`verify` is `verify_combined`
- internals of firmware parsing were reworked to support signing firmware headers