TREZOR One Dev Kits

Introduction

This hobbyist project documents kits that developers can use to explore, develop, test, and debug the open source TREZOR One hardware and software.

Warning

These kits do NOT produce production TREZOR One cryptocurrency hardware wallet devices.

If you want an official TREZOR One hardware wallet, see: https://shop.trezor.io/

When contrasted to official production hardware, these kits are less safe to use for non-development purposes.

Necessarily, different selections were made for the key security properties of these developer kits vs. production hardware. For example, when used as documented here, these kits purposefully leave debug capabilities enabled, and do not apply write protections to bootloader flash memory. This is so that developers may repeatedly develop, test, and debug all types of changes.

Production hardware irreversibly disables debug capabilities and Device Firmware Upgrade (DFU) mode, and protects key memory areas as part of reducing attack surface and increasing depth of defenses. There may be other subtle, yet meaningful, weaknesses as well, depending on your usage and threat model.

USE THESE KITS AT YOUR OWN RISK

Hardware

TREZOR One Open Source Hardware Reference Documentation

Kit Contents: v0 (the breadboard version)

v0
Fig H1. - v0

Kit Contents: v1 (the first printed wiring board [PWB] version)

Bare PWB (top)
Fig H2. - Bare PWB (top)
Bare PWB (bottom)
Fig H3. - Bare PWB (bottom)
Assembled PWB (top)
Fig H4. - Assembled PWB (top)
Assembled PWB (bottom)
Fig H5. - Assembled PWB (bottom)
Front angle view (with large 1.54 inch display)
Fig H6. - Front angle view (with large 1.54 inch display)
Side view, PWB and display module stacked on the dev board
Fig H7. - Side view, PWB and display module stacked on the dev board
Installed and running (large 1.54 inch display)
Fig H8. - Installed and running (large 1.54 inch display)
Installed and running (regular 0.96 inch display)
Fig H9. - Installed and running (regular 0.96 inch display)
0.96 inch SSD1306 driven display and 1.54 inch SSD1309 driven display side-by-side (top)
Fig H10. - 0.96 inch SSD1306 driven display and 1.54 inch SSD1309 driven display side-by-side (top)
0.96 inch SSD1306 driven display and 1.54 inch SSD1309 driven display side-by-side (bottom)
Fig H11. - 0.96 inch SSD1306 driven display and 1.54 inch SSD1309 driven display side-by-side (bottom)

Kit Contents: v2 (the second printed wiring board [PWB] version)

Bare PWB (top)
Fig H12. - Bare PWB (top)
Bare PWB (bottom)
Fig H13. - Bare PWB (bottom)
Assembled PWB (top)
Fig H14. - Assembled PWB (top)
Assembled PWB (bottom)
Fig H15. - Assembled PWB (bottom)
Front angle view (with large 1.54 inch display)
Fig H16. - Front angle view (with large 1.54 inch display)
Side view, PWB and display module stacked on the dev board
Fig H17. - Side view, PWB and display module stacked on the dev board
Installed and running (large 1.54 inch display)
Fig H18. - Installed and running (large 1.54 inch display)
Installed and running (regular 0.96 inch display)
Fig H19. - Installed and running (regular 0.96 inch display)

About the Kits

One key difference between these kits and production hardware is the microcontroller (MCU) used. Production hardware uses the STM32F205RET6 (and more recently, the STM32F205RGT6) MCU and these kits use the STM32F405RGT6 MCU. Note: the STM32F205RET6 is documented to have 512KB of flash memory, but it actually has 1MB. Apparently, it is more cost efficient for ST to not develop different chip-wafers. The former is an ARM® Cortex®-M3 and the latter is an ARM® Cortex®-M4. The Cortex-M4 architecture is a backwards compatible superset of Cortex-M3. The additional features, like hard float capability, do not matter for this project. The STM32F405RGT6 has 1MB of flash memory, a core clock frequency adjustable up to 168MHz (including the 205's 120MHz; with matching clock tree), and 128KB of SRAM (same as the 205; the 405 has an additional 64KB of CCMRAM, giving it 192KB of usable RAM). The STM32F405RGT6 is pin-to-pin compatible with the STM32F205RET6/STM32F205RGT6 and uses the same TRNG (reference: STM32F405xx datasheet section 2.1, and AN4230 section 1.2.1).

The Waveshare Core405R dev board has an 8MHz high-speed external (HSE) crystal (matching the reference hardware), a STM32F405RGT6 MCU, a USB connector, power circuitry, SWD debug interface, boot mode select switch, and all the pins needed, broken out and available for use.

Setup

Wiring the Debug Adapter to the Dev Board

Pay attention to the pinout that is specified on the debug adapter. Also, pay attention to the location of the notch on the header housing. Note that the white rectangle printed next to pin 5 on the pinout specification in Figure H20 denotes the notch.

Connect the Debug Adapter's SWDIO, SWCLK, and GND pins (any one of the ground pins is sufficient) to the corresponding pins on the Dev Board's SWD connector.

The Debug Adapter with Pinout Silkscreen
Fig H20. - The Debug Adapter with Pinout Silkscreen
The Debug Adapter Notch
Fig H21. - The Debug Adapter Notch
The Dev Board SWD Connector
Fig H22. - The Dev Board SWD Connector
The Debug Adapter Wired - Debug Adapter Side
Fig H23. - The Debug Adapter Wired - Debug Adapter Side
The Debug Adapter Wired - Dev Board Side
Fig H24. - The Debug Adapter Wired - Dev Board Side
The Debug Adapter Wired
Fig H25. - The Debug Adapter Wired

Note: Instead of using the JTAG/SWD connector, the debug adapter's SWDIO, SWCLK, and GND pins may also be connected to the dev board's PA13, PA14, and GND pins, respectively.

The Debug Adapter Wired - Without using the JTAG/SWD Connector
Fig H26. - The Debug Adapter Wired - Without using the JTAG/SWD Connector
The Debug Adapter Wired - Samtec SSQ-116-03-T-D Headers
Fig H27. - The Debug Adapter Wired - Samtec SSQ-116-03-T-D Headers
The Debug Adapter Wired - Using the PA13, PA14, and GND Pins
Fig H28. - The Debug Adapter Wired - Using the PA13, PA14, and GND Pins

Setting Dev Board Jumpers and Switches

Set the Dev Board jumpers and switches as shown in Figure H29.

The Dev Board Jumper and Switch Configuration
Fig H29. - The Dev Board Jumper and Switch Configuration

Wiring the Dev Board to the Breadboard Display and Switches

Use the following table to wire between the dev board and appropriate tie points on your breadboard. The following pictures are also helpful if you don't quite understand.

Pins on the dev board are documented by the silkscreen on the other side of the board. Pins on the display module are also documented by silkscreen.

Dev Board PinBreadboard PinAlternate NameComment
PC5Button 2Either button pin; connect GND to the other button pin; button is Active-Low
PA4CSChip SelectPin 7 on Pictured Display
PB0DCData/CommandPin 6 on Pictured Display
PB1RESResetPin 5 on Pictured Display
PA7SDAMOSIPin 4 on Pictured Display
PA5SCKSCLKPin 3 on Pictured Display
3.3VVDD3V3Pin 2 on Pictured Display
GNDGNDGroundPin 1 on Pictured Display
PC2Button 1Either button pin; connect GND to the other button pin; button is Active-Low
Dev Board Wiring
Fig H30. - Dev Board Wiring
Dev Board Wiring
Fig H31. - Dev Board Wiring
Dev Board Wiring
Fig H32. - Dev Board Wiring
Dev Board Wiring
Fig H33. - Dev Board Wiring
Dev Board Wiring
Fig H34. - Dev Board Wiring
Dev Board Wiring
Fig H35. - Dev Board Wiring

Software

TREZOR One Open Source Software Main Repository

Setup

This setup process comprises steps to install development and debugging tools on a temporary computer, then build and install a bootloader and firmware on the kit's MCU.
The following setup process was documented while running an Ubuntu 18.04 LTS Desktop (Bionic Beaver) Live CD as user ubuntu.

  1. Connect to the Internet
  2. cd /tmp/
  3. Install required software packages
    • sudo add-apt-repository universe
    • sudo apt-get update
    • sudo apt-get -y install git openocd make protobuf-compiler libprotobuf-dev python-pip
    • sudo -H pip install ecdsa protobuf
    • sudo apt-get -y install python3-dev python3-pip cython3 libusb-1.0-0-dev libudev-dev libssl-dev (note: required for python-trezor testing)
    • sudo -H pip3 install trezor[ethereum,hidapi] (note: required for python-trezor testing)
    • sudo apt-get -y install openjdk-8-jdk (note: at least a Java SE 8 JRE is required for the eclipse GUI)
  4. Download tools
    • GNU ARM Embedded Toolchain
      • wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2
    • Eclipse IDE for C/C++ Developers (get the latest 64-bit Linux version available; Eclipse Photon R (4.8.0) or newer)
      • wget http://mirror.math.princeton.edu/pub/eclipse/technology/epp/downloads/release/photon/R/eclipse-cpp-photon-R-linux-gtk-x86_64.tar.gz
  5. Extract tools
    • tar xjf gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2
  6. Add extracted tool binaries to PATH environment variable
    • /bin/echo 'export PATH="/tmp/gcc-arm-none-eabi-7-2018-q2-update/bin:$PATH"' >> ~/.bashrc
    • source ~/.bashrc
  7. Setup udev rules to make the USB devices available to non-root users
    • /bin/echo -e '# 0483:df11 STMicroelectronics STM Device in DFU Mode' > /tmp/99-dev-kit.rules
    • /bin/echo -e 'SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="df11", MODE="0666"' >> /tmp/99-dev-kit.rules
    • /bin/echo -e '# 0483:3748 STMicroelectronics ST-LINK/V2' >> /tmp/99-dev-kit.rules
    • /bin/echo -e 'SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="3748", MODE="0666"' >> /tmp/99-dev-kit.rules
    • /bin/echo -e '# 0483:374b STMicroelectronics ST-LINK/V2.1 (Nucleo-F103RB)' >> /tmp/99-dev-kit.rules
    • /bin/echo -e 'SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="374b", MODE="0666"' >> /tmp/99-dev-kit.rules
    • /bin/echo -e '# 534c:0001 SatoshiLabs Bitcoin Wallet [TREZOR]' >> /tmp/99-dev-kit.rules
    • /bin/echo -e 'SUBSYSTEM=="usb", ATTR{idVendor}=="534c", ATTR{idProduct}=="0001", MODE="0666"' >> /tmp/99-dev-kit.rules
    • /bin/echo -e 'KERNEL=="hidraw*", ATTRS{idVendor}=="534c", ATTRS{idProduct}=="0001", MODE="0666"' >> /tmp/99-dev-kit.rules
    • /bin/echo -e '# 1209:53c0 SatoshiLabs TREZOR Model T Bootloader' >> /tmp/99-dev-kit.rules
    • /bin/echo -e 'SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="53c0", MODE="0666"' >> /tmp/99-dev-kit.rules
    • /bin/echo -e 'KERNEL=="hidraw*", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="53c0", MODE="0666"' >> /tmp/99-dev-kit.rules
    • /bin/echo -e '# 1209:53c1 SatoshiLabs TREZOR Model T' >> /tmp/99-dev-kit.rules
    • /bin/echo -e 'SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="53c1", MODE="0666"' >> /tmp/99-dev-kit.rules
    • /bin/echo -e 'KERNEL=="hidraw*", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="53c1", MODE="0666"' >> /tmp/99-dev-kit.rules
    • sudo cp /tmp/99-dev-kit.rules /etc/udev/rules.d/
  8. Download, build, and package the TREZOR One bootloader and firmware from source code
    Note: The "export MEMORY_PROTECT=0" is what controls the code that locks the bootloader's flash memory on your dev board.
    Warning: If you compile with MEMORY_PROTECT=1 (the default if not set as directed below), and run it on your dev board, you will lock your MCU's bootloader flash memory sectors and permanently disable debug capabilities.
    • git clone https://github.com/trezor/trezor-mcu.git
    • cd trezor-mcu/
    • git submodule update --init --recursive
    • make -C vendor/libopencm3/ lib/stm32/f2
    • export MEMORY_PROTECT=0
    • make
    • make -C bootloader/ align
    • make -C vendor/nanopb/generator/proto/
    • make -C firmware/protob/
    • make -C firmware/ sign
    • cp bootloader/bootloader.bin bootloader/combine/bl.bin
    • cp firmware/trezor.bin bootloader/combine/fw.bin
    • cd bootloader/combine/ && ./prepare.py
  9. Plug both the dev board and the debug adapter into your computer's USB ports.
  10. openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg
  11. Open another terminal, then connect gdb to the OpenOCD process that was started in the previous step, and send OpenOCD the flash command to write the combined bootloader and firmware binary to MCU flash memory:
    arm-none-eabi-gdb --nx -ex 'set remotetimeout unlimited' -ex 'set confirm off' -ex 'target remote 127.0.0.1:3333' -ex 'monitor reset halt' -ex 'monitor flash write_image erase /tmp/trezor-mcu/bootloader/combine/combined.bin 0x08000000' -ex 'monitor reset halt' /tmp/trezor-mcu/bootloader/bootloader.elf
  12. Flash has now been written. Set some test breakpoints and practice debugging code:
    • (gdb) b *reset_handler
    • (gdb) b *memory_protect
    • (gdb) b *load_app
    • (gdb) layout regs
    • (gdb) si
    • (gdb) c
    • (gdb) c
    • (gdb) d
    • (gdb) file ../../firmware/trezor.elf
    • (gdb) b *main
    • (gdb) c
    • (gdb) c
    • (gdb) Press Ctrl + C to interrupt software execution
    • (gdb) quit

    Note that the symbol files were changed above at a point in the debugging process near bootloader-exit/firmware-entry. This was done in order to add breakpoints based on symbols relevant to the code being executed.

    Also, be sure to check the display module and progress past the unofficial firmware warning message by pressing the appropriate buttons. Otherwise, it will seem as though your debugging session has simply stopped working. In fact, the code is just waiting for your user input.

  13. Done flashing the software to the dev board and debugging. Kill the OpenOCD process and unplug the debug adapter and dev board.
  14. Test the bootloader and firmware just loaded onto the dev board:
    • Plug-in the dev board and progress past the unofficial firmware warnings (if you are running the firmware that was compiled earlier and not an officially signed firmware).
    • cd /tmp/
    • git clone https://github.com/trezor/python-trezor.git
    • cd python-trezor/
    • git submodule update --init --recursive
    • python3 setup.py prebuild
    • ./trezorctl wipe_device
    • ./trezorctl load_device -m 'fun fun fun fun fun fun fun fun fun fun fun fun fun fun fun fun fun fun fun fun fun fun fun agent'
    • ./trezorctl get_address -c Bitcoin -t address -n "m/44'/0'/0'/0/0"
      (note: this is a legacy base58 encoded p2pkh)
    • ./trezorctl get_address -c Bitcoin -t p2shsegwit -n "m/49'/0'/0'/0/0"
      (note: this is a base58 encoded p2wpkh-p2sh)
    • ./trezorctl get_address -c Bitcoin -t segwit -n "m/84'/0'/0'/0/0"
      (note: this is a bech32 encoded p2wpkh)
    • ./trezorctl get_address -c Litecoin -t address -n "m/44'/2'/0'/0/0"
    • ./trezorctl get_address -c Litecoin -t p2shsegwit -n "m/49'/2'/0'/0/0"
    • ./trezorctl get_address -c Litecoin -t segwit -n "m/84'/2'/0'/0/0"
    • ./trezorctl get_address -c Namecoin -t address -n "m/44'/7'/0'/0/0"
  15. Install eclipse so that a graphical environment can be used for debugging:
    • cd /tmp/
    • tar xzf eclipse-cpp-photon-R-linux-gtk-x86_64.tar.gz
    • mkdir -p /tmp/eclipse-workspace
  16. Start OpenOCD and eclipse. Setup a debug configuration and debug graphically.
    The full process to setup graphical debugging is shown in the video in Figure S1.
    Fig S1. - Eclipse Graphical Debugging Demonstration Video

Going Further

Loading and Running an Officially Signed Firmware

UPDATE: Loading officially signed firmware versions 1.6.1 and later onto your dev kit is NOT recommended. Doing so, risks your bootloader flash memory sectors being locked. For more info, see this and this.

In the setup process, a self-built bootloader and firmware was compiled, combined, and then loaded onto the MCU flash. To use an officially signed firmware, simply replace fw.bin in the setup process above before running prepare.py. Then run the prepare.py and load the newly created combined.bin onto the MCU.

An officially signed firmware can be downloaded with:
wget -O fw.bin https://wallet.trezor.io/data/firmware/trezor-1.5.2.bin

Running Standalone

These kits can be used in a standalone configuration; without the debug adapter connected. Simply unplug and/or detach the debug adapter from the dev board and plug the dev board into your computer's USB port.

The v0 Kit Running Standalone without Debug Adapter Connected
Fig O1. - The v0 Kit Running Standalone without Debug Adapter Connected

Flashing in DFU mode with dfu-util instead of flashing with OpenOCD

The setup process used OpenOCD to flash code into the MCU's flash memory and was done in non-Device Firmware Upgrade (DFU) mode. DFU mode can be used instead. Doing so just requires using different tools, moving a switch, and unplugging and replugging the dev board a couple of times. Using DFU mode is a little less convenient when compared to the flash process used above.

To use DFU mode

Getting Info About and Erasing MCU Flash

Compiling and Using the Latest Version of OpenOCD

Upgrading ST-LINK USB Debug Adapter Firmware

Questions

More Open Source TREZOR Related Work