mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-29 19:08:12 +00:00
e0fd890661
Header is generated with ./tools/build_vendorheader 'key1,key2,key3' 2 1.1 SatoshiLabs assets/satoshilabs.png micropython/firmware/vendorheader.bin where - keyN is a 64 character hex string encoding the public key - 2 encodes 2/3 key scheme - 1.1 is the version number (major, minor) - SatoshiLabs is the vendor name - satoshilabs.png is the vendor image Updated the firmware compilation that it adds vendor header and updated loader that it handles vendor header to be present.
110 lines
4.8 KiB
Markdown
110 lines
4.8 KiB
Markdown
# TREZOR Core Bootloader
|
|
|
|
TREZOR initialization in split into two stages. See [Memory Layout](memory.md) for info about in which sectors each stage is stored.
|
|
|
|
First stage (bootloader) is stored in write-protected area, which means it is non-upgradable.
|
|
Only second stage (loader) update is allowed.
|
|
|
|
## First Stage - Bootloader
|
|
|
|
First stage checks the integrity and signatures of the second stage and runs it if everything is OK.
|
|
|
|
If first stage bootloader finds a valid second stage loader image on the SD card (in raw format, no filesystem),
|
|
it will replace the internal second stage, allowing a second stage update via SD card.
|
|
|
|
## Second Stage - Loader
|
|
|
|
Second stage checks the integrity and signatures of the firmware and runs it if everything is OK.
|
|
|
|
If second stage loader detects a pressed finger on the display or there is no firmware loaded in the device,
|
|
it will start in a firmware update mode, allowing a firmware update via USB.
|
|
|
|
## Common notes
|
|
|
|
* Hash function used for computing data digest for signatures is BLAKE2s.
|
|
* Signature system is Ed25519 (allows combining signatures by multiple keys into one).
|
|
* All multibyte integer values are little endian.
|
|
* There is a tool called [binctl](../tools/binctl) which checks validity of the loader/firmware images including their headers.
|
|
|
|
## Loader Format
|
|
|
|
TREZOR Core (second stage) loader consists of 2 parts:
|
|
|
|
1. loader header
|
|
2. loader code
|
|
|
|
### Loader Header
|
|
|
|
Total length of loader header is always 512 bytes.
|
|
|
|
| offset | length | name | description |
|
|
|-------:|-------:|------|-------------|
|
|
| 0x0000 | 4 | magic | firmware magic `TRZL` |
|
|
| 0x0004 | 4 | hdrlen | length of the loader header |
|
|
| 0x0008 | 4 | expiry | valid until timestamp (0=infinity) |
|
|
| 0x000C | 4 | codelen | length of the loader code (without the header) |
|
|
| 0x0010 | 1 | vmajor | version (major) |
|
|
| 0x0011 | 1 | vminor | version (minor) |
|
|
| 0x0012 | 1 | vpatch | version (patch) |
|
|
| 0x0013 | 1 | vbuild | version (build) |
|
|
| 0x0014 | 427 | reserved | not used yet (zeroed) |
|
|
| 0x01BF | 1 | sigmask | SatoshiLabs signature indexes (bitmap) |
|
|
| 0x01C0 | 64 | sig | SatoshiLabs aggregated signature |
|
|
|
|
## Firmware Format
|
|
|
|
TREZOR Core firmware consists of 3 parts:
|
|
|
|
1. vendor header
|
|
2. firmware header
|
|
3. firmware code
|
|
|
|
### Vendor Header
|
|
|
|
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.
|
|
|
|
| offset | length | name | description |
|
|
|-------:|-------:|------|-------------|
|
|
| 0x0000 | 4 | magic | firmware magic `TRZV` |
|
|
| 0x0004 | 4 | hdrlen | length of the vendor header (multiple of 512) |
|
|
| 0x0008 | 4 | expiry | valid until timestamp (0=infinity) |
|
|
| 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 |
|
|
| 0x0010 | 32 | vpub1 | vendor pubkey 1 |
|
|
| ... | ... | ... | ... |
|
|
| ? | 32 | vpubn | vendor pubkey n |
|
|
| ? | 1 | vstr_len | vendor string length |
|
|
| ? | ? | vstr | vendor string |
|
|
| ? | ? | vstrpad | padding to a multiple of 4 bytes |
|
|
| ? | ? | vimg | vendor image (in [TOIf format](toif.md)) |
|
|
| ? | ? | reserved | padding to an address that is -65 modulo 512 |
|
|
| ? | 1 | sigmask | SatoshiLabs signature indexes (bitmap) |
|
|
| ? | 64 | sig | SatoshiLabs aggregated signature |
|
|
|
|
### Firmware Header
|
|
|
|
Total length of firmware header is always 512 bytes.
|
|
|
|
| offset | length | name | description |
|
|
|-------:|-------:|------|-------------|
|
|
| 0x0000 | 4 | magic | firmware magic `TRZF` |
|
|
| 0x0004 | 4 | hdrlen | length of the firmware header |
|
|
| 0x0008 | 4 | expiry | valid until timestamp (0=infinity) |
|
|
| 0x000C | 4 | codelen | length of the firmware code (without the header) |
|
|
| 0x0010 | 1 | vmajor | version (major) |
|
|
| 0x0011 | 1 | vminor | version (minor) |
|
|
| 0x0012 | 1 | vpatch | version (patch) |
|
|
| 0x0013 | 1 | vbuild | version (build) |
|
|
| 0x0014 | 427 | reserved | not used yet (zeroed) |
|
|
| 0x01BF | 1 | sigmask | vendor signature indexes (bitmap) |
|
|
| 0x01C0 | 64 | sig | vendor aggregated signature |
|
|
|
|
## Various ideas
|
|
|
|
* 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.
|
|
* Storage wiping rule: Don't erase storage when old FW and new FW are signed using the same key set. Otherwise erase.
|
|
* 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.
|