Trezor One firmware format

Historically Trezor One has been using 256-byte header (w/ TRZR magic string) followed by the actual firmware. Since version 1.8.0, different 1024-byte header (w/ TRZF magic string) is in use, and building firmware from this repository produces firmware image containing such header followed by firmware code.

Official release firmware contains both these headers for compatibility with old bootloaders. That means there is a 256-byte TRZR header followed by 1024-byte TRZF header followed by code.

  • Hash function used for computing data digest for signatures is SHA256.
  • Signature system is ECDSA over SECP256k1.
  • All multibyte integer values are little endian.

Legacy Header

Total length of legacy header is always 256 bytes.

offsetlengthnamedescription
0x00004magicfirmware magic TRZR
0x00044codelenlength of V2 header + code (length of code before 1.8.0)
0x00081sigindex1index of key for sig1
0x00091sigindex2index of key for sig2
0x000A1sigindex3index of key for sig3
0x000B1flagsunused since 1.8.0 (zeroed)
0x000C52reservednot used yet (zeroed)
0x004064sig1signature #1
0x008064sig2signature #2
0x00C064sig3signature #3

Signature verification:

  • Calculate SHA256 digest of firmware without this header.
  • Verify signature sig1 of the digest against public key with index sigindex1 in V1_BOOTLOADER_KEYS.
  • Repeat for sig2 and sig3. Indexes must be distinct.

V2 Header

This header has the same format as Model T Firmware Header, however due to different signature scheme the sigmask and sig fields are zeroed and part of the reserved space is used for T1-specific fields sig1-sig3, sigindex1-sigindex3. Total length of v2 header is always 1024 bytes.

offsetlengthnamedescription
0x00004magicfirmware magic TRZF
0x00044hdrlenlength of the firmware header
0x00084expiryvalid until timestamp (0=infinity)
0x000C4codelenlength of the firmware code (without the header)
0x00101vmajorversion (major)
0x00111vminorversion (minor)
0x00121vpatchversion (patch)
0x00131vbuildversion (build)
0x00141fix_vmajorversion of last critical bugfix (major)
0x00151fix_vminorversion of last critical bugfix (minor)
0x00161fix_vpatchversion of last critical bugfix (patch)
0x00171fix_vbuildversion of last critical bugfix (build)
0x00188reservednot used yet (zeroed)
0x002032hash1hash of the first code chunk excluding both the legacy and the v2 header (129792 B)
0x004032hash2hash of the second code chunk (128 KiB), zeroed if unused
............
0x020032hash16hash of the last possible code chunk (128 KiB), zeroed if unused
0x022064sig1signature #1
0x026064sig2signature #2
0x02A064sig3signature #3
0x02E01sigindex1index of key for sig1
0x02E11sigindex2index of key for sig2
0x02E21sigindex3index of key for sig3
0x02E3220reservednot used yet (zeroed)
0x03BF1reserved_sigmaskunused in T1 (zeroed)
0x03C064reserved_sigunused in T1 (zeroed)

Signature verification:

  • Calculate SHA256 digest of the entire header with sig1-sig3 and sigindex1-sigindex3 zeroed out.
  • Verify signature sig1 of the digest against public key with index sigindex1 in V1_BOOTLOADER_KEYS.
  • Repeat for sig2 and sig3. Indexes must be distinct.