mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-29 01:28:10 +00:00
legacy/intermediate_fw: Intermediate firmware for T1 (#1084)
* legacy/intermediate_fw: skeleton FW with RAM shim function * legacy/intermediate_fw: reboot from RAM * legacy/intermediate_fw: flash erase from RAM * legacy/intermediate_fw: port flash erase body from cm3 * legacy/intermediate_fw: erase works with flash unlock * legacy/intermediate_fw: wait for flash controller ready * legacy/intermediate_fw: cleanup and add comments * legacy/intermediate_fw: disable IRQ before reboot * legacy/intermediate_fw: also erase storage * legacy/intermediate_fw: style * legacy/intermediate_fw: dialogs for update bootloader/erase FW * legacy/intermediate_fw: style * legacy/intermediate_fw: add bootloader replacement code * legacy/intermediate_fw: add CI build script for intermediate FW * legacy/intermediate_fw: call bootloader update * legacy/intermediate_fw: add bootloader update dependency * legacy/intermediate_fw: change setup() at start of main * legacy/intermediate_fw: deduplicate code * docs: table for MEMORY_PROTECT combinations that work on T1 * legacy/intermediate_fw: deduplicate code * legacy/intermediate_fw: check if running in privileged mode * legacy/intermediate_fw: style * legacy/intermediate_fw: ChangeLog * legacy/intermediate_fw: make version match latest bootloader included * legacy/intermediate_fw: style
This commit is contained in:
parent
21b4c5b60e
commit
ff3b10a329
@ -105,3 +105,21 @@ Switch your device to bootloader mode, then execute:
|
|||||||
```sh
|
```sh
|
||||||
trezorctl firmware-update -f build/legacy/firmware/trezor.bin
|
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.
|
||||||
|
|
||||||
|
@ -130,7 +130,13 @@ static int known_bootloader(int r, const uint8_t *hash) {
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
#if MEMORY_PROTECT
|
||||||
uint8_t hash[32] = {0};
|
uint8_t hash[32] = {0};
|
||||||
int r = memory_bootloader_hash(hash);
|
int r = memory_bootloader_hash(hash);
|
||||||
@ -178,11 +184,13 @@ void check_bootloader(void) {
|
|||||||
// check whether the write was OK
|
// check whether the write was OK
|
||||||
r = memory_bootloader_hash(hash);
|
r = memory_bootloader_hash(hash);
|
||||||
if (r == 32 && 0 == memcmp(hash, bl_hash, 32)) {
|
if (r == 32 && 0 == memcmp(hash, bl_hash, 32)) {
|
||||||
|
if (shutdown_on_success) {
|
||||||
// OK -> show info and halt
|
// OK -> show info and halt
|
||||||
layoutDialog(&bmp_icon_info, NULL, NULL, NULL, _("Update finished"),
|
layoutDialog(&bmp_icon_info, NULL, NULL, NULL, _("Update finished"),
|
||||||
_("successfully."), NULL, _("Please reconnect"),
|
_("successfully."), NULL, _("Please reconnect"),
|
||||||
_("the device."), NULL);
|
_("the device."), NULL);
|
||||||
shutdown();
|
shutdown();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,4 +200,6 @@ void check_bootloader(void) {
|
|||||||
_("contact our support."), NULL);
|
_("contact our support."), NULL);
|
||||||
shutdown();
|
shutdown();
|
||||||
#endif
|
#endif
|
||||||
|
// prevent compiler warning when MEMORY_PROTECT==0
|
||||||
|
(void)shutdown_on_success;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#ifndef __BL_CHECK_H__
|
#ifndef __BL_CHECK_H__
|
||||||
#define __BL_CHECK_H__
|
#define __BL_CHECK_H__
|
||||||
|
|
||||||
void check_bootloader(void);
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
void check_bootloader(bool shutdown_on_success);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -123,7 +123,7 @@ int main(void) {
|
|||||||
// unpredictable stack protection checks
|
// unpredictable stack protection checks
|
||||||
oledInit();
|
oledInit();
|
||||||
#else
|
#else
|
||||||
check_bootloader();
|
check_bootloader(true);
|
||||||
setupApp();
|
setupApp();
|
||||||
__stack_chk_guard = random32(); // this supports compiler provided
|
__stack_chk_guard = random32(); // this supports compiler provided
|
||||||
// unpredictable stack protection checks
|
// unpredictable stack protection checks
|
||||||
|
28
legacy/intermediate_fw/ChangeLog
Normal file
28
legacy/intermediate_fw/ChangeLog
Normal file
@ -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
legacy/intermediate_fw/Makefile
Normal file
60
legacy/intermediate_fw/Makefile
Normal file
@ -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
legacy/intermediate_fw/bl_check.c
Symbolic link
1
legacy/intermediate_fw/bl_check.c
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../firmware/bl_check.c
|
1
legacy/intermediate_fw/bl_check.h
Symbolic link
1
legacy/intermediate_fw/bl_check.h
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../firmware/bl_check.h
|
1
legacy/intermediate_fw/bl_data.py
Symbolic link
1
legacy/intermediate_fw/bl_data.py
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../firmware/bl_data.py
|
1
legacy/intermediate_fw/bootloader.dat
Symbolic link
1
legacy/intermediate_fw/bootloader.dat
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../firmware/bootloader.dat
|
1
legacy/intermediate_fw/gettext.h
Symbolic link
1
legacy/intermediate_fw/gettext.h
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../firmware/gettext.h
|
1
legacy/intermediate_fw/header.S
Symbolic link
1
legacy/intermediate_fw/header.S
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../firmware/header.S
|
125
legacy/intermediate_fw/trezor.c
Normal file
125
legacy/intermediate_fw/trezor.c
Normal file
@ -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
legacy/intermediate_fw/trezor.h
Normal file
40
legacy/intermediate_fw/trezor.h
Normal file
@ -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
legacy/intermediate_fw/version.h
Normal file
8
legacy/intermediate_fw/version.h
Normal file
@ -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
legacy/script/cibuild_intermediate_fw
Executable file
15
legacy/script/cibuild_intermediate_fw
Executable file
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user