Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intermediate firmware for T1 #1084

Merged
merged 25 commits into from
Aug 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1b533e9
legacy/intermediate_fw: skeleton FW with RAM shim function
hiviah Jun 22, 2020
014851d
legacy/intermediate_fw: reboot from RAM
hiviah Jun 22, 2020
0c6a641
legacy/intermediate_fw: flash erase from RAM
hiviah Jun 22, 2020
d8b7ab4
legacy/intermediate_fw: port flash erase body from cm3
hiviah Jun 22, 2020
6e98916
legacy/intermediate_fw: erase works with flash unlock
hiviah Jun 22, 2020
c4fa1c4
legacy/intermediate_fw: wait for flash controller ready
hiviah Jun 22, 2020
40ac9d3
legacy/intermediate_fw: cleanup and add comments
hiviah Jun 22, 2020
1b89a08
legacy/intermediate_fw: disable IRQ before reboot
hiviah Jun 22, 2020
f2c7040
legacy/intermediate_fw: also erase storage
hiviah Jun 23, 2020
0b1d359
legacy/intermediate_fw: style
hiviah Jun 23, 2020
053f8ae
legacy/intermediate_fw: dialogs for update bootloader/erase FW
hiviah Jun 23, 2020
7397b8e
legacy/intermediate_fw: style
hiviah Jun 23, 2020
176a17b
legacy/intermediate_fw: add bootloader replacement code
hiviah Jun 23, 2020
87a2af3
legacy/intermediate_fw: add CI build script for intermediate FW
hiviah Jun 23, 2020
76b5c51
legacy/intermediate_fw: call bootloader update
hiviah Jun 23, 2020
163e44f
legacy/intermediate_fw: add bootloader update dependency
hiviah Jun 23, 2020
38e6646
legacy/intermediate_fw: change setup() at start of main
hiviah Jun 24, 2020
ef11bc4
legacy/intermediate_fw: deduplicate code
hiviah Jun 25, 2020
57d844b
docs: table for MEMORY_PROTECT combinations that work on T1
hiviah Jun 25, 2020
fe1ba5b
legacy/intermediate_fw: deduplicate code
hiviah Jun 25, 2020
4bfb05a
legacy/intermediate_fw: check if running in privileged mode
hiviah Jun 25, 2020
22447c1
legacy/intermediate_fw: style
hiviah Jun 25, 2020
3be23c4
legacy/intermediate_fw: ChangeLog
hiviah Jun 25, 2020
d368f1a
legacy/intermediate_fw: make version match latest bootloader included
hiviah Jun 29, 2020
dab3d81
legacy/intermediate_fw: style
hiviah Jun 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions docs/legacy/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,21 @@ Switch your device to bootloader mode, then execute:
```sh
trezorctl firmware-update -f build/legacy/firmware/trezor.bin
```

## Combining bootloader and firmware with various `MEMORY_PROTECT` settings, signed/unsigned

Not all combinations of bootloader and firmware will work. This depends on
3 variables: MEMORY_PROTECT of bootloader, MEMORY_PROTECT of firmware, whether firmware is signed

This table shows the result for bootloader 1.8.0+ and 1.9.1+:

| Bootloader MEMORY_PROTECT | Firmware MEMORY_PROTECT | Is firmware officially signed? | Result |
| ------------------------- | ----------------------- | ------------------------------ | ------------------------------------------------------------------------------------------ |
| 1 | 1 | yes | works, official configuration |
| 1 | 1 | no | hardfault in header.S when setting VTOR and stack |
| 0 | 1 | no | works, but don't forget to comment out `check_bootloader`, otherwise it'll get overwritten |
| 0 | 0 | no | hard fault because header.S doesn't set VTOR and stack right |
| 1 | 0 | no | works |

The other three possibilities with signed firmware and `MEMORY_PROTECT!=0` for bootloader/firmware don't exist.

22 changes: 16 additions & 6 deletions legacy/firmware/bl_check.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,13 @@ static int known_bootloader(int r, const uint8_t *hash) {
}
#endif

void check_bootloader(void) {
/**
* If bootloader is older and known, replace with newer bootloader.
* If bootloader is unknown, halt with error message.
*
* @param shutdown_on_success: if true, shuts down device instead of return
*/
void check_bootloader(bool shutdown_on_success) {
#if MEMORY_PROTECT
uint8_t hash[32] = {0};
int r = memory_bootloader_hash(hash);
Expand Down Expand Up @@ -178,11 +184,13 @@ void check_bootloader(void) {
// check whether the write was OK
r = memory_bootloader_hash(hash);
if (r == 32 && 0 == memcmp(hash, bl_hash, 32)) {
// OK -> show info and halt
layoutDialog(&bmp_icon_info, NULL, NULL, NULL, _("Update finished"),
_("successfully."), NULL, _("Please reconnect"),
_("the device."), NULL);
shutdown();
if (shutdown_on_success) {
// OK -> show info and halt
layoutDialog(&bmp_icon_info, NULL, NULL, NULL, _("Update finished"),
_("successfully."), NULL, _("Please reconnect"),
_("the device."), NULL);
shutdown();
}
return;
}
}
Expand All @@ -192,4 +200,6 @@ void check_bootloader(void) {
_("contact our support."), NULL);
shutdown();
#endif
// prevent compiler warning when MEMORY_PROTECT==0
(void)shutdown_on_success;
}
4 changes: 3 additions & 1 deletion legacy/firmware/bl_check.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#ifndef __BL_CHECK_H__
#define __BL_CHECK_H__

void check_bootloader(void);
#include <stdbool.h>

void check_bootloader(bool shutdown_on_success);

#endif
2 changes: 1 addition & 1 deletion legacy/firmware/trezor.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ int main(void) {
// unpredictable stack protection checks
oledInit();
#else
check_bootloader();
check_bootloader(true);
setupApp();
__stack_chk_guard = random32(); // this supports compiler provided
// unpredictable stack protection checks
Expand Down
28 changes: 28 additions & 0 deletions legacy/intermediate_fw/ChangeLog
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]

### Added

### Deprecated

### Removed

### Fixed

### Security

------------

### Older changelog:

Version 1.8.0 [Jun 2020]
* Initial version of intermediate firmware
* Updates bootloader to 1.8.0
* Deletes storage and the intermediate firmware code
* Version of intermediate firmware matches bootloader version included

60 changes: 60 additions & 0 deletions legacy/intermediate_fw/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
APPVER = 1.8.0

NAME = trezor

OBJS += trezor.o
OBJS += header.o
OBJS += bl_check.o
OBJS += ../vendor/trezor-crypto/memzero.o
OBJS += ../vendor/trezor-crypto/sha2.o

OPTFLAGS ?= -Og


../vendor/trezor-crypto/bip32.o: OPTFLAGS = -O3
../vendor/trezor-crypto/bip39.o: OPTFLAGS = -O3
../vendor/trezor-crypto/ecdsa.o: OPTFLAGS = -O3
../vendor/trezor-crypto/sha2.o: OPTFLAGS = -O3
../vendor/trezor-crypto/secp256k1.o: OPTFLAGS = -O3

include ../Makefile.include
CFLAGS:=$(filter-out -fstack-protector-all,$(CFLAGS))

DEBUG_LINK ?= 0
DEBUG_LOG ?= 0

CFLAGS += -Wno-sequence-point
CFLAGS += -I../vendor/nanopb -Iprotob -DPB_FIELD_16BIT=1 -DPB_ENCODE_ARRAYS_UNPACKED=1 -DPB_VALIDATE_UTF8=1
CFLAGS += -DDEBUG_LINK=$(DEBUG_LINK)
CFLAGS += -DDEBUG_LOG=$(DEBUG_LOG)
CFLAGS += -DSCM_REVISION='"$(shell git rev-parse HEAD | sed 's:\(..\):\\x\1:g')"'
CFLAGS += -DUSE_MONERO=0
ifneq ($(BITCOIN_ONLY),1)
CFLAGS += -DUSE_ETHEREUM=1
CFLAGS += -DUSE_NEM=1
MAKO_RENDER_FLAG =
else
CFLAGS += -DUSE_ETHEREUM=0
CFLAGS += -DUSE_NEM=0
MAKO_RENDER_FLAG = --bitcoin-only
endif

%:: %.mako defs
@printf " MAKO $@\n"
$(Q)$(PYTHON) ../vendor/trezor-common/tools/cointool.py render $(MAKO_RENDER_FLAG) $@.mako

bl_data.h: bl_data.py bootloader.dat
@printf " PYTHON bl_data.py\n"
$(Q)$(PYTHON) bl_data.py

clean::
rm -f bl_data.h
find -maxdepth 1 -name "*.mako" | sed 's/.mako$$//' | xargs rm -f

FIRMWARE_T1_START = 0x08010000
flash_intermediate_fw: trezor.bin
openocd -f interface/stlink-v2.cfg -c "transport select hla_swd" -f target/stm32f2x.cfg -c "init; reset halt; flash write_image erase $< $(FIRMWARE_T1_START); exit"

openocd_reset:
$(OPENOCD) -c "init; reset; exit"

1 change: 1 addition & 0 deletions legacy/intermediate_fw/bl_check.c
1 change: 1 addition & 0 deletions legacy/intermediate_fw/bl_check.h
1 change: 1 addition & 0 deletions legacy/intermediate_fw/bl_data.py
1 change: 1 addition & 0 deletions legacy/intermediate_fw/bootloader.dat
1 change: 1 addition & 0 deletions legacy/intermediate_fw/gettext.h
1 change: 1 addition & 0 deletions legacy/intermediate_fw/header.S
125 changes: 125 additions & 0 deletions legacy/intermediate_fw/trezor.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* This file is part of the Trezor project, https://trezor.io/
*
* Copyright (C) 2014 Pavol Rusnak <stick@satoshilabs.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/

#include "trezor.h"
#include <libopencm3/stm32/desig.h>
#include <libopencm3/stm32/flash.h>
#include <vendor/libopencm3/include/libopencmsis/core_cm3.h>
#include "bitmaps.h"
#include "bl_check.h"
#include "layout.h"
#include "memory.h"
#include "memzero.h"
#include "oled.h"
#include "rng.h"
#include "setup.h"
#include "timer.h"
#include "util.h"

/** Sector erase operation extracted from libopencm3 - flash_erase_sector
* so it can run from RAM
*/
static void __attribute__((noinline, section(".data")))
erase_sector(uint8_t sector, uint32_t psize) {
// Wait for flash controller to be ready
while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY)
;
// Set program word width
FLASH_CR &= ~(FLASH_CR_PROGRAM_MASK << FLASH_CR_PROGRAM_SHIFT);
FLASH_CR |= psize << FLASH_CR_PROGRAM_SHIFT;

/* Sector numbering is not contiguous internally! */
if (sector >= 12) {
sector += 4;
}

FLASH_CR &= ~(FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT);
FLASH_CR |= (sector & FLASH_CR_SNB_MASK) << FLASH_CR_SNB_SHIFT;
FLASH_CR |= FLASH_CR_SER;
FLASH_CR |= FLASH_CR_STRT;

// Wait for flash controller to be ready
while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY)
;
FLASH_CR &= ~FLASH_CR_SER;
FLASH_CR &= ~(FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT);
}

static void __attribute__((noinline, section(".data")))
erase_firmware_and_storage(void) {
// Flash unlock
FLASH_KEYR = FLASH_KEYR_KEY1;
FLASH_KEYR = FLASH_KEYR_KEY2;

// Erase storage sectors to prevent firmware downgrade to vulnerable version
for (int i = FLASH_STORAGE_SECTOR_FIRST; i <= FLASH_STORAGE_SECTOR_LAST;
i++) {
erase_sector(i, FLASH_CR_PROGRAM_X32);
}

// Erase firmware sectors
for (int i = FLASH_CODE_SECTOR_FIRST; i <= FLASH_CODE_SECTOR_LAST; i++) {
erase_sector(i, FLASH_CR_PROGRAM_X32);
}

// Flash lock
FLASH_CR |= FLASH_CR_LOCK;
}

void __attribute__((noinline, noreturn, section(".data"))) reboot_device(void) {
__disable_irq();
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
while (1)
;
}

/** Entry point of RAM shim that deletes old FW, storage and reboot */
void __attribute__((noinline, noreturn, section(".data")))
erase_fw_and_reboot(void) {
erase_firmware_and_storage();
reboot_device();

for (;;)
; // never reached, but compiler would generate error
}

int main(void) {
setupApp();
__stack_chk_guard = random32(); // this supports compiler provided
// unpredictable stack protection checks
oledInit();
if (is_mode_unprivileged()) {
layoutDialog(&bmp_icon_warning, NULL, NULL, NULL, "Cannot update", NULL,
NULL, "Unprivileged mode", "Unsigned firmware", NULL);
shutdown();
}

mpu_config_off(); // needed for flash writable, RAM RWX
timer_init();
check_bootloader(false);

layoutDialog(&bmp_icon_warning, NULL, NULL, NULL, "Erasing old data", NULL,
NULL, "DO NOT UNPLUG", "YOUR TREZOR!", NULL);
oledRefresh();

// from this point the execution is from RAM instead of flash
erase_fw_and_reboot();

return 0;
}
40 changes: 40 additions & 0 deletions legacy/intermediate_fw/trezor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* This file is part of the Trezor project, https://trezor.io/
*
* Copyright (C) 2014 Pavol Rusnak <stick@satoshilabs.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __TREZOR_H__
#define __TREZOR_H__

#include <stdint.h>
#include "version.h"

#define STR(X) #X
#define VERSTR(X) STR(X)

#ifndef DEBUG_LINK
#define DEBUG_LINK 0
#endif

#ifndef DEBUG_LOG
#define DEBUG_LOG 0
#endif

/* Screen timeout */
extern uint32_t system_millis_lock_start;

#endif
8 changes: 8 additions & 0 deletions legacy/intermediate_fw/version.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Matches the bootloader version included in this firmware
#define VERSION_MAJOR 1
#define VERSION_MINOR 8
#define VERSION_PATCH 0

#define FIX_VERSION_MAJOR 1
#define FIX_VERSION_MINOR 8
#define FIX_VERSION_PATCH 0
15 changes: 15 additions & 0 deletions legacy/script/cibuild_intermediate_fw
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash

# script/cibuild_intermediate_fw:
# Setup environment for CI to build intermediate firmware.

set -e

cd "$(dirname "$0")/.."

make -C vendor/libopencm3 lib/stm32/f2

make libtrezor.a

make -C intermediate_fw all sign