2017-03-20 14:49:11 +00:00
# TREZOR Core Bootloader
2016-04-25 18:43:48 +00:00
2017-03-20 14:58:47 +00:00
TREZOR initialization in split into two stages. See [Memory Layout ](memory.md ) for info about in which sectors each stage is stored.
2016-04-25 20:02:12 +00:00
2017-03-20 14:58:47 +00:00
First stage (bootloader) is stored in write-protected area, which means it is non-upgradable.
Only second stage (loader) update is allowed.
2016-04-25 18:43:48 +00:00
2017-03-20 14:58:47 +00:00
## First Stage - Bootloader
2017-02-08 15:36:19 +00:00
First stage checks the integrity and signatures of the second stage and runs it if everything is OK.
2017-03-20 14:58:47 +00:00
If first stage bootloader finds a valid second stage loader image on the SD card (in raw format, no filesystem),
2017-02-08 15:36:19 +00:00
it will replace the internal second stage, allowing a second stage update via SD card.
2017-03-20 14:58:47 +00:00
## Second Stage - Loader
2017-02-08 15:36:19 +00:00
Second stage checks the integrity and signatures of the firmware and runs it if everything is OK.
2017-03-20 14:58:47 +00:00
If second stage loader detects a pressed finger on the display or there is no firmware loaded in the device,
2017-02-08 15:36:19 +00:00
it will start in a firmware update mode, allowing a firmware update via USB.
2017-02-08 14:42:52 +00:00
2017-03-20 14:49:11 +00:00
## Common notes
2017-02-08 14:42:52 +00:00
2017-03-22 00:53:25 +00:00
* Hash function used for computing data digest for signatures is BLAKE2s.
* Signature system is Ed25519 (allows combining signatures by multiple keys into one).
2017-02-08 14:42:52 +00:00
* All multibyte integer values are little endian.
2017-03-30 20:58:00 +00:00
* There is a tool called [binctl ](../tools/binctl ) which checks validity of the loader/firmware images including their headers.
2017-02-08 14:42:52 +00:00
2017-03-20 14:58:47 +00:00
## Loader Format
2017-02-08 14:42:52 +00:00
2017-03-20 14:58:47 +00:00
TREZOR Core (second stage) loader consists of 2 parts:
2017-02-08 14:42:52 +00:00
2017-03-20 14:58:47 +00:00
1. loader header
2. loader code
2017-02-08 14:42:52 +00:00
2017-03-20 14:58:47 +00:00
### Loader Header
2017-02-08 14:42:52 +00:00
2017-03-31 21:54:59 +00:00
Total length of loader header is always 512 bytes.
2017-02-08 14:42:52 +00:00
| offset | length | name | description |
|-------:|-------:|------|-------------|
2017-03-20 14:58:47 +00:00
| 0x0000 | 4 | magic | firmware magic `TRZL` |
| 0x0004 | 4 | hdrlen | length of the loader header |
2017-02-08 14:42:52 +00:00
| 0x0008 | 4 | expiry | valid until timestamp (0=infinity) |
2017-03-20 14:58:47 +00:00
| 0x000C | 4 | codelen | length of the loader code (without the header) |
2017-02-08 14:42:52 +00:00
| 0x0010 | 1 | vmajor | version (major) |
| 0x0011 | 1 | vminor | version (minor) |
| 0x0012 | 1 | vpatch | version (patch) |
| 0x0013 | 1 | vbuild | version (build) |
2017-03-31 21:54:59 +00:00
| 0x0014 | 427 | reserved | not used yet (zeroed) |
2017-04-01 00:32:05 +00:00
| 0x01BF | 1 | sigmask | SatoshiLabs signature indexes (bitmap) |
| 0x01C0 | 64 | sig | SatoshiLabs aggregated signature |
2017-02-08 14:42:52 +00:00
2017-03-20 14:49:11 +00:00
## Firmware Format
2017-02-08 14:42:52 +00:00
TREZOR Core firmware consists of 3 parts:
2016-04-25 18:43:48 +00:00
1. vendor header
2. firmware header
3. firmware code
2017-03-20 14:49:11 +00:00
### Vendor Header
2016-04-25 18:43:48 +00:00
2017-04-01 13:45:50 +00:00
Total length of vendor header is 84 + 32 * (number of pubkeys) + (length of vendor string rounded up to multiple of 4) + (length of vendor image) bytes rounded up to the closest multiple of 512 bytes.
2016-05-10 14:42:20 +00:00
2016-04-25 18:43:48 +00:00
| offset | length | name | description |
|-------:|-------:|------|-------------|
| 0x0000 | 4 | magic | firmware magic `TRZV` |
2017-04-01 13:45:50 +00:00
| 0x0004 | 4 | hdrlen | length of the vendor header (multiple of 512) |
2017-02-08 14:42:52 +00:00
| 0x0008 | 4 | expiry | valid until timestamp (0=infinity) |
2017-02-09 15:26:15 +00:00
| 0x000C | 1 | vmajor | version (major) |
| 0x000D | 1 | vminor | version (minor) |
| 0x000E | 1 | vsig_m | number of signatures needed to run the firmware from this vendor |
| 0x000F | 1 | vsig_n | number of different pubkeys vendor provides for signing |
2016-05-10 14:42:20 +00:00
| 0x0010 | 32 | vpub1 | vendor pubkey 1 |
2016-04-25 18:43:48 +00:00
| ... | ... | ... | ... |
| ? | 32 | vpubn | vendor pubkey n |
2016-05-10 14:42:20 +00:00
| ? | 1 | vstr_len | vendor string length |
| ? | ? | vstr | vendor string |
2017-04-01 13:45:50 +00:00
| ? | ? | vstrpad | padding to a multiple of 4 bytes |
2016-05-10 14:42:20 +00:00
| ? | ? | vimg | vendor image (in [TOIf format ](toif.md )) |
2017-04-01 13:45:50 +00:00
| ? | ? | reserved | padding to an address that is -65 modulo 512 |
2017-04-01 00:32:05 +00:00
| ? | 1 | sigmask | SatoshiLabs signature indexes (bitmap) |
| ? | 64 | sig | SatoshiLabs aggregated signature |
2016-04-25 18:43:48 +00:00
2017-03-20 14:49:11 +00:00
### Firmware Header
2016-04-25 18:43:48 +00:00
2017-03-31 21:54:59 +00:00
Total length of firmware header is always 512 bytes.
2016-05-10 14:42:20 +00:00
2016-04-25 18:43:48 +00:00
| offset | length | name | description |
|-------:|-------:|------|-------------|
| 0x0000 | 4 | magic | firmware magic `TRZF` |
2017-02-08 15:36:19 +00:00
| 0x0004 | 4 | hdrlen | length of the firmware header |
2017-02-08 14:42:52 +00:00
| 0x0008 | 4 | expiry | valid until timestamp (0=infinity) |
2017-02-08 15:36:19 +00:00
| 0x000C | 4 | codelen | length of the firmware code (without the header) |
2016-05-09 11:14:55 +00:00
| 0x0010 | 1 | vmajor | version (major) |
| 0x0011 | 1 | vminor | version (minor) |
| 0x0012 | 1 | vpatch | version (patch) |
| 0x0013 | 1 | vbuild | version (build) |
2017-03-31 21:54:59 +00:00
| 0x0014 | 427 | reserved | not used yet (zeroed) |
2017-04-01 00:32:05 +00:00
| 0x01BF | 1 | sigmask | vendor signature indexes (bitmap) |
| 0x01C0 | 64 | sig | vendor aggregated signature |
2016-09-15 11:39:19 +00:00
2017-03-20 14:49:11 +00:00
## Various ideas
2016-09-15 11:39:19 +00:00
2017-03-20 14:58:47 +00:00
* Loader should be able to read vendor + firmware header and send info about FW to client in features message.
* Loader should not try to run firmware if there is not any.
2016-09-15 11:39:19 +00:00
* Storage wiping rule: Don't erase storage when old FW and new FW are signed using the same key set. Otherwise erase.
2017-03-20 14:58:47 +00:00
* Loader should send error to client when firmware update fails and allow client to try one more time. This prevents storage area erasure by accident.