@ -34,91 +34,15 @@
# include "ecdsa.h"
# include "secp256k1.h"
# include "memzero.h"
# include "memory.h"
# include "usb21_standard.h"
# include "webusb.h"
# include "winusb.h"
# define FIRMWARE_MAGIC "TRZR"
# define USB_INTERFACE_INDEX_MAIN 0
# define ENDPOINT_ADDRESS_IN (0x81)
# define ENDPOINT_ADDRESS_OUT (0x01)
static bool brand_new_firmware ;
static bool old_was_unsigned ;
static const struct usb_device_descriptor dev_descr = {
. bLength = USB_DT_DEVICE_SIZE ,
. bDescriptorType = USB_DT_DEVICE ,
. bcdUSB = 0x0210 ,
. bDeviceClass = 0 ,
. bDeviceSubClass = 0 ,
. bDeviceProtocol = 0 ,
. bMaxPacketSize0 = 64 ,
. idVendor = 0x1209 ,
. idProduct = 0x53c0 ,
. bcdDevice = 0x0100 ,
. iManufacturer = 1 ,
. iProduct = 2 ,
. iSerialNumber = 3 ,
. bNumConfigurations = 1 ,
} ;
static const struct usb_endpoint_descriptor endpoints [ 2 ] = { {
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = ENDPOINT_ADDRESS_IN ,
. bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT ,
. wMaxPacketSize = 64 ,
. bInterval = 1 ,
} , {
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = ENDPOINT_ADDRESS_OUT ,
. bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT ,
. wMaxPacketSize = 64 ,
. bInterval = 1 ,
} } ;
static const struct usb_interface_descriptor iface [ ] = { {
. bLength = USB_DT_INTERFACE_SIZE ,
. bDescriptorType = USB_DT_INTERFACE ,
. bInterfaceNumber = USB_INTERFACE_INDEX_MAIN ,
. bAlternateSetting = 0 ,
. bNumEndpoints = 2 ,
. bInterfaceClass = USB_CLASS_VENDOR ,
. bInterfaceSubClass = 0 ,
. bInterfaceProtocol = 0 ,
. iInterface = 0 ,
. endpoint = endpoints ,
. extra = NULL ,
. extralen = 0 ,
} } ;
static const struct usb_interface ifaces [ ] = { {
. num_altsetting = 1 ,
. altsetting = iface ,
} } ;
static const struct usb_config_descriptor config = {
. bLength = USB_DT_CONFIGURATION_SIZE ,
. bDescriptorType = USB_DT_CONFIGURATION ,
. wTotalLength = 0 ,
. bNumInterfaces = 1 ,
. bConfigurationValue = 1 ,
. iConfiguration = 0 ,
. bmAttributes = 0x80 ,
. bMaxPower = 0x32 ,
. interface = ifaces ,
} ;
static const char * usb_strings [ ] = {
" SatoshiLabs " ,
" TREZOR " ,
" 000000000000000000000000 " ,
} ;
# include "usb_desc.h"
# include "usb_send.h"
# include "usb_erase.h"
enum {
STATE_READY ,
@ -130,121 +54,77 @@ enum {
} ;
static uint32_t flash_pos = 0 , flash_len = 0 ;
static uint32_t chunk_idx = 0 ;
static char flash_state = STATE_READY ;
static uint8_t flash_anim = 0 ;
static uint16_t msg_id = 0xFFFF ;
static uint32_t msg_size = 0 ;
static uint8_t meta_backup [ FLASH_META_LEN ] ;
static void send_msg_success ( usbd_device * dev )
{
uint8_t response [ 64 ] ;
memzero ( response , sizeof ( response ) ) ;
// response: Success message (id 2), payload len 0
memcpy ( response ,
// header
" ?## "
// msg_id
" \x00 \x02 "
// msg_size
" \x00 \x00 \x00 \x00 " ,
9 ) ;
while ( usbd_ep_write_packet ( dev , ENDPOINT_ADDRESS_IN , response , 64 ) ! = 64 ) { }
}
static void send_msg_failure ( usbd_device * dev )
{
uint8_t response [ 64 ] ;
memzero ( response , sizeof ( response ) ) ;
// response: Failure message (id 3), payload len 2
// - code = 99 (Failure_FirmwareError)
memcpy ( response ,
// header
" ?## "
// msg_id
" \x00 \x03 "
// msg_size
" \x00 \x00 \x00 \x02 "
// data
" \x08 " " \x63 " ,
11 ) ;
while ( usbd_ep_write_packet ( dev , ENDPOINT_ADDRESS_IN , response , 64 ) ! = 64 ) { }
}
static void send_msg_features ( usbd_device * dev )
{
uint8_t response [ 64 ] ;
memzero ( response , sizeof ( response ) ) ;
// response: Features message (id 17), payload len 25
// - vendor = "trezor.io"
// - major_version = VERSION_MAJOR
// - minor_version = VERSION_MINOR
// - patch_version = VERSION_PATCH
// - bootloader_mode = True
// - firmware_present = True/False
// - model = "1"
memcpy ( response ,
// header
" ?## "
// msg_id
" \x00 \x11 "
// msg_size
" \x00 \x00 \x00 \x16 "
// data
" \x0a " " \x09 " " trezor.io "
" \x10 " VERSION_MAJOR_CHAR
" \x18 " VERSION_MINOR_CHAR
" \x20 " VERSION_PATCH_CHAR
" \x28 " " \x01 "
" \x90 \x01 " " \x00 "
" \xaa " " \x01 " " 1 " ,
34 ) ;
response [ 30 ] = brand_new_firmware ? 0x01 : 0x00 ;
while ( usbd_ep_write_packet ( dev , ENDPOINT_ADDRESS_IN , response , 64 ) ! = 64 ) { }
}
static uint32_t FW_HEADER [ FLASH_FWHEADER_LEN / sizeof ( uint32_t ) ] ;
static uint32_t FW_CHUNK [ FW_CHUNK_SIZE / sizeof ( uint32_t ) ] ;
static void send_msg_buttonrequest_firmwarecheck( usbd_device * dev )
static void check_and_write_chunk ( void )
{
uint8_t response [ 64 ] ;
memzero ( response , sizeof ( response ) ) ;
// response: ButtonRequest message (id 26), payload len 2
// - code = ButtonRequest_FirmwareCheck (9)
memcpy ( response ,
// header
" ?## "
// msg_id
" \x00 \x1a "
// msg_size
" \x00 \x00 \x00 \x02 "
// data
" \x08 " " \x09 " ,
11
) ;
while ( usbd_ep_write_packet ( dev , ENDPOINT_ADDRESS_IN , response , 64 ) ! = 64 ) { }
}
uint32_t offset = ( chunk_idx = = 0 ) ? FLASH_FWHEADER_LEN : 0 ;
uint32_t chunk_pos = flash_pos % FW_CHUNK_SIZE ;
if ( chunk_pos = = 0 ) {
chunk_pos = FW_CHUNK_SIZE ;
}
uint8_t hash [ 32 ] ;
SHA256_CTX ctx ;
sha256_Init ( & ctx ) ;
sha256_Update ( & ctx , ( const uint8_t * ) FW_CHUNK + offset , chunk_pos - offset ) ;
if ( chunk_pos < 64 * 1024 ) {
// pad with FF
for ( uint32_t i = chunk_pos ; i < 64 * 1024 ; i + = 4 ) {
sha256_Update ( & ctx , ( const uint8_t * ) " \xFF \xFF \xFF \xFF " , 4 ) ;
}
}
sha256_Final ( & ctx , hash ) ;
static void backup_metadata ( uint8_t * backup )
{
memcpy ( backup , FLASH_PTR ( FLASH_META_START ) , FLASH_META_LEN ) ;
}
const image_header * hdr = ( const image_header * ) FW_HEADER ;
// invalid chunk sent
if ( 0 ! = memcmp ( hash , hdr - > hashes + chunk_idx * 32 , 32 ) ) {
// erase storage
erase_storage ( ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
shutdown ( ) ;
return ;
}
static void restore_metadata ( const uint8_t * backup )
{
flash_wait_for_last_operation ( ) ;
flash_clear_status_flags ( ) ;
flash_unlock ( ) ;
for ( int i = 0 ; i < FLASH_META_LEN / 4 ; i + + ) {
const uint32_t * w = ( const uint32_t * ) ( backup + i * 4 ) ;
flash_program_word ( FLASH_META_START + i * 4 , * w ) ;
for ( uint32_t i = offset / sizeof ( uint32_t ) ; i < chunk_pos / sizeof ( uint32_t ) ; i + + ) {
flash_program_word ( FLASH_FWHEADER_START + chunk_idx * FW_CHUNK_SIZE + i * sizeof ( uint32_t ) , FW_CHUNK [ i ] ) ;
}
flash_wait_for_last_operation ( ) ;
flash_lock ( ) ;
// all done
if ( flash_len = = flash_pos ) {
// check remaining chunks if any
for ( uint32_t i = chunk_idx + 1 ; i < 16 ; i + + ) {
// hash should be empty if the chunk is unused
if ( 0 ! = memcmp ( hdr - > hashes + i * 32 , " \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " , 32 ) ) {
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
shutdown ( ) ;
return ;
}
}
}
memzero ( FW_CHUNK , sizeof ( FW_CHUNK ) ) ;
chunk_idx + + ;
}
static void rx_callback ( usbd_device * dev , uint8_t ep )
{
( void ) ep ;
static uint16_t msg_id = 0xFFFF ;
static uint8_t buf [ 64 ] __attribute__ ( ( aligned ( 4 ) ) ) ;
static uint8_t towrite [ 4 ] __attribute__ ( ( aligned ( 4 ) ) ) ;
static uint 32_t w ;
static int wi ;
static int old_was_signed ;
if ( usbd_ep_read_packet ( dev , ENDPOINT_ADDRESS_OUT , buf , 64 ) ! = 64 ) return ;
@ -258,7 +138,6 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
}
// struct.unpack(">HL") => msg, size
msg_id = ( buf [ 3 ] < < 8 ) + buf [ 4 ] ;
msg_size = ( ( uint32_t ) buf [ 5 ] < < 24 ) + ( buf [ 6 ] < < 16 ) + ( buf [ 7 ] < < 8 ) + buf [ 8 ] ;
}
if ( flash_state = = STATE_READY | | flash_state = = STATE_OPEN ) {
@ -277,26 +156,9 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
}
if ( msg_id = = 0x0005 ) { // WipeDevice message (id 5)
layoutDialog ( & bmp_icon_question , " Cancel " , " Confirm " , NULL , " Do you really want to " , " wipe the device? " , NULL , " All data will be lost. " , NULL , NULL ) ;
do {
delay ( 100000 ) ;
buttonUpdate ( ) ;
} while ( ! button . YesUp & & ! button . NoUp ) ;
if ( button . YesUp ) {
flash_wait_for_last_operation ( ) ;
flash_clear_status_flags ( ) ;
flash_unlock ( ) ;
// erase metadata area
for ( int i = FLASH_META_SECTOR_FIRST ; i < = FLASH_META_SECTOR_LAST ; i + + ) {
layoutProgress ( " PREPARING ... Please wait " , 1000 * ( i - FLASH_META_SECTOR_FIRST ) / ( FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST ) ) ;
flash_erase_sector ( i , FLASH_CR_PROGRAM_X32 ) ;
}
// erase code area
for ( int i = FLASH_CODE_SECTOR_FIRST ; i < = FLASH_CODE_SECTOR_LAST ; i + + ) {
layoutProgress ( " PREPARING ... Please wait " , 1000 * ( i - FLASH_META_SECTOR_FIRST ) / ( FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST ) ) ;
flash_erase_sector ( i , FLASH_CR_PROGRAM_X32 ) ;
}
flash_wait_for_last_operation ( ) ;
flash_lock ( ) ;
bool but = get_button_response ( ) ;
if ( but ) {
erase_storage_code_progress ( ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_ok , NULL , NULL , NULL , " Device " , " successfully wiped. " , NULL , " You may now " , " unplug your TREZOR. " , NULL ) ;
send_msg_success ( dev ) ;
@ -311,59 +173,31 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
if ( flash_state = = STATE_OPEN ) {
if ( msg_id = = 0x0006 ) { // FirmwareErase message (id 6)
if ( ! brand_new_firmware ) {
bool proceed = false ;
if ( firmware_present_new ( ) ) {
layoutDialog ( & bmp_icon_question , " Abort " , " Continue " , NULL , " Install new " , " firmware? " , NULL , " Never do this without " , " your recovery card! " , NULL ) ;
do {
delay ( 100000 ) ;
buttonUpdate ( ) ;
} while ( ! button . YesUp & & ! button . NoUp ) ;
proceed = get_button_response ( ) ;
} else {
proceed = true ;
}
if ( brand_new_firmware | | button . YesUp ) {
// check whether current firmware is signed
if ( ! brand_new_firmware & & SIG_OK = = signatures_ok ( NULL ) ) {
old_was_unsigned = false ;
// backup metadata
backup_metadata ( meta_backup ) ;
if ( proceed ) {
// check whether the current firmware is signed (old or new method)
if ( firmware_present_new ( ) ) {
const image_header * hdr = ( const image_header * ) FLASH_PTR ( FLASH_FWHEADER_START ) ;
old_was_signed = ( SIG_OK = = signatures_new_ok ( hdr , NULL ) ) & & ( SIG_OK = = check_firmware_hashes ( hdr ) ) ;
} else if ( firmware_present_old ( ) ) {
old_was_signed = signatures_old_ok ( ) ;
} else {
old_was_unsigned = true ;
}
flash_wait_for_last_operation ( ) ;
flash_clear_status_flags ( ) ;
flash_unlock ( ) ;
// erase metadata area
for ( int i = FLASH_META_SECTOR_FIRST ; i < = FLASH_META_SECTOR_LAST ; i + + ) {
layoutProgress ( " PREPARING ... Please wait " , 1000 * ( i - FLASH_META_SECTOR_FIRST ) / ( FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST ) ) ;
flash_erase_sector ( i , FLASH_CR_PROGRAM_X32 ) ;
old_was_signed = SIG_FAIL ;
}
// erase code area
for ( int i = FLASH_CODE_SECTOR_FIRST ; i < = FLASH_CODE_SECTOR_LAST ; i + + ) {
layoutProgress ( " PREPARING ... Please wait " , 1000 * ( i - FLASH_META_SECTOR_FIRST ) / ( FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST ) ) ;
flash_erase_sector ( i , FLASH_CR_PROGRAM_X32 ) ;
}
layoutProgress ( " INSTALLING ... Please wait " , 0 ) ;
flash_wait_for_last_operation ( ) ;
flash_lock ( ) ;
// check that metadata was succesfully erased
// flash status register should show now error and
// the config block should contain only \xff.
uint8_t hash [ 32 ] ;
sha256_Raw ( FLASH_PTR ( FLASH_META_START ) , FLASH_META_LEN , hash ) ;
if ( ( FLASH_SR & ( FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_WRPERR ) ) ! = 0
| | memcmp ( hash , " \x2d \x86 \x4c \x0b \x78 \x9a \x43 \x21 \x4e \xee \x85 \x24 \xd3 \x18 \x20 \x75 \x12 \x5e \x5c \xa2 \xcd \x52 \x7f \x35 \x82 \xec \x87 \xff \xd9 \x40 \x76 \xbc " , 32 ) ! = 0 ) {
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
return ;
}
erase_code_progress ( ) ;
send_msg_success ( dev ) ;
flash_state = STATE_FLASHSTART ;
return ;
} else {
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_warning , NULL , NULL , NULL , " Firmware installation " , " aborted. " , NULL , " You may now " , " unplug your TREZOR. " , NULL ) ;
}
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_warning , NULL , NULL , NULL , " Firmware installation " , " aborted. " , NULL , " You may now " , " unplug your TREZOR. " , NULL ) ;
return ;
}
return ;
@ -375,41 +209,47 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
shutdown ( ) ;
return ;
}
// read payload length
const uint8_t * p = buf + 10 ;
flash_len = readprotobufint ( & p ) ;
if ( flash_len > FLASH_TOTAL_SIZE + FLASH_META_DESC_LEN - ( FLASH_APP_START - FLASH_ORIGIN ) ) { // firmware is too big
if ( flash_len < = FLASH_FWHEADER_LEN ) { // firmware is too small
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Firmware is too small. " , NULL , " Get official firmware " , " from trezor.io/start " , NULL , NULL ) ;
return ;
}
if ( flash_len > FLASH_FWHEADER_LEN + FLASH_APP_LEN ) { // firmware is too big
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Firmware is too big. " , NULL , " Get official firmware " , " from trezor.io/start " , NULL , NULL ) ;
return ;
}
// check firmware magic
if ( memcmp ( p , FIRMWARE_MAGIC , 4 ) ! = 0 ) {
if ( memcmp ( p , & FIRMWARE_MAGIC _NEW , 4 ) ! = 0 ) {
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Wrong firmware header. " , NULL , " Get official firmware " , " from trezor.io/start " , NULL , NULL ) ;
return ;
}
memzero ( FW_HEADER , sizeof ( FW_HEADER ) ) ;
memzero ( FW_CHUNK , sizeof ( FW_CHUNK ) ) ;
flash_state = STATE_FLASHING ;
p + = 4 ; // Don't flash firmware header yet.
flash_pos = 4 ;
wi = 0 ;
flash_unlock ( ) ;
flash_pos = 0 ;
chunk_idx = 0 ;
w = 0 ;
while ( p < buf + 64 ) {
towrite[ wi ] = * p ;
w = ( w > > 8 ) | ( * p < < 24 ) ; // assign byte to first byte of uint32_t w
wi + + ;
if ( wi = = 4 ) {
const uint32_t * w = ( uint32_t * ) towrite ;
flash_program_word ( FLASH_META_START + flash_pos , * w ) ;
FW_HEADER [ flash_pos / 4 ] = w ;
flash_pos + = 4 ;
wi = 0 ;
}
p + + ;
}
flash_lock ( ) ;
return ;
}
return ;
@ -420,34 +260,44 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
shutdown ( ) ;
return ;
}
const uint8_t * p = buf + 1 ;
static uint8_t flash_anim = 0 ;
if ( flash_anim % 32 = = 4 ) {
layoutProgress ( " INSTALLING ... Please wait " , 1000 * flash_pos / flash_len ) ;
}
flash_anim + + ;
flash_unlock ( ) ;
const uint8_t * p = buf + 1 ;
while ( p < buf + 64 & & flash_pos < flash_len ) {
towrite[ wi ] = * p ;
w = ( w > > 8 ) | ( * p < < 24 ) ; // assign byte to first byte of uint32_t w
wi + + ;
if ( wi = = 4 ) {
const uint32_t * w = ( const uint32_t * ) towrite ;
if ( flash_pos < FLASH_META_DESC_LEN ) {
flash_program_word ( FLASH_META_START + flash_pos , * w ) ; // the first 256 bytes of firmware is metadata descriptor
if ( flash_pos < FLASH_FWHEADER_LEN ) {
FW_HEADER [ flash_pos / 4 ] = w ;
} else {
flash_program_word ( FLASH_APP_START + ( flash_pos - FLASH_META_DESC_LEN ) , * w ) ; // the rest is code
FW_CHUNK [ ( flash_pos % FW_CHUNK_SIZE ) / 4 ] = w ;
}
flash_pos + = 4 ;
wi = 0 ;
// finished the whole chunk
if ( flash_pos % FW_CHUNK_SIZE = = 0 ) {
check_and_write_chunk ( ) ;
}
}
p + + ;
}
flash_lock ( ) ;
// flashing done
if ( flash_pos = = flash_len ) {
// flush remaining data in the last chunk
if ( flash_pos % FW_CHUNK_SIZE > 0 ) {
check_and_write_chunk ( ) ;
}
flash_state = STATE_CHECK ;
if ( ! brand_new_firmware ) {
const image_header * hdr = ( const image_header * ) FW_HEADER ;
if ( SIG_OK ! = signatures_new_ok ( hdr , NULL ) ) {
send_msg_buttonrequest_firmwarecheck ( dev ) ;
return ;
}
@ -458,55 +308,69 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
if ( flash_state = = STATE_CHECK ) {
if ( ! brand_new_firmware ) {
// use the firmware header from RAM
const image_header * hdr = ( const image_header * ) FW_HEADER ;
bool hash_check_ok ;
// show fingerprint of unsigned firmware
if ( SIG_OK ! = signatures_new_ok ( hdr , NULL ) ) {
if ( msg_id ! = 0x001B ) { // ButtonAck message (id 27)
return ;
}
uint8_t hash [ 32 ] ;
sha256_Raw ( FLASH_PTR ( FLASH_APP_START ) , flash_len - FLASH_META_DESC_LEN , hash ) ;
layoutFirmwareHash ( hash ) ;
do {
delay ( 100000 ) ;
buttonUpdate ( ) ;
} while ( ! button . YesUp & & ! button . NoUp ) ;
compute_firmware_fingerprint ( hdr , hash ) ;
layoutFirmwareFingerprint ( hash ) ;
hash_check_ok = get_button_response ( ) ;
} else {
hash_check_ok = true ;
}
bool hash_check_ok = brand_new_firmware | | button . YesUp ;
layoutProgress ( " INSTALLING ... Please wait " , 1000 ) ;
uint8_t flags = * FLASH_PTR ( FLASH_META_FLAGS ) ;
// wipe storage if:
// 0) there was no firmware
// 1) old firmware was unsigned
// 2) firmware restore flag isn't set
// 3) signatures are not ok
if ( brand_new_firmware | | old_was_unsigned | | ( flags & 0x01 ) = = 0 | | SIG_OK ! = signatures_ok ( NULL ) ) {
memzero ( meta_backup , sizeof ( meta_backup ) ) ;
// 1) old firmware was unsigned or not present
// 2) signatures are not OK
// 3) hashes are not OK
if ( SIG_OK ! = old_was_signed | | SIG_OK ! = signatures_new_ok ( hdr , NULL ) | | SIG_OK ! = check_firmware_hashes ( hdr ) ) {
// erase storage
erase_storage ( ) ;
// check erasure
uint8_t hash [ 32 ] ;
sha256_Raw ( FLASH_PTR ( FLASH_STORAGE_START ) , FLASH_STORAGE_LEN , hash ) ;
if ( memcmp ( hash , " \x2d \x86 \x4c \x0b \x78 \x9a \x43 \x21 \x4e \xee \x85 \x24 \xd3 \x18 \x20 \x75 \x12 \x5e \x5c \xa2 \xcd \x52 \x7f \x35 \x82 \xec \x87 \xff \xd9 \x40 \x76 \xbc " , 32 ) ! = 0 ) {
send_msg_failure ( dev ) ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
shutdown ( ) ;
return ;
}
}
// copy new firmware header
memcpy ( meta_backup , ( void * ) FLASH_META_START , FLASH_META_DESC_LEN ) ;
// write "TRZR" in header only when hash was confirmed
flash_wait_for_last_operation ( ) ;
flash_clear_status_flags ( ) ;
flash_unlock ( ) ;
// write firmware header only when hash was confirmed
if ( hash_check_ok ) {
memcpy ( meta_backup , FIRMWARE_MAGIC , 4 ) ;
for ( size_t i = 0 ; i < FLASH_FWHEADER_LEN / sizeof ( uint32_t ) ; i + + ) {
flash_program_word ( FLASH_FWHEADER_START + i * sizeof ( uint32_t ) , FW_HEADER [ i ] ) ;
}
} else {
memzero ( meta_backup , 4 ) ;
for ( size_t i = 0 ; i < FLASH_FWHEADER_LEN / sizeof ( uint32_t ) ; i + + ) {
flash_program_word ( FLASH_FWHEADER_START + i * sizeof ( uint32_t ) , 0 ) ;
}
}
// no need to erase, because we are not changing any already flashed byte.
restore_metadata ( meta_backup ) ;
memzero ( meta_backup , sizeof ( meta_backup ) ) ;
flash_wait_for_last_operation ( ) ;
flash_lock ( ) ;
flash_state = STATE_END ;
if ( hash_check_ok ) {
layoutDialog ( & bmp_icon_ok , NULL , NULL , NULL , " New firmware " , " successfully installed. " , NULL , " You may now " , " unplug your TREZOR. " , NULL ) ;
send_msg_success ( dev ) ;
shutdown ( ) ;
} else {
layoutDialog ( & bmp_icon_warning , NULL , NULL , NULL , " Firmware installation " , " aborted. " , NULL , " You need to repeat " , " the procedure with " , " the correct firmware. " ) ;
send_msg_failure ( dev ) ;
shutdown ( ) ;
}
return ;
}
}
static void set_config ( usbd_device * dev , uint16_t wValue )
@ -531,7 +395,7 @@ static const struct usb_bos_descriptor bos_descriptor = {
. capabilities = capabilities
} ;
void usbInit ( void )
static void usbInit ( void )
{
usbd_dev = usbd_init ( & otgfs_usb_driver , & dev_descr , & config , usb_strings , sizeof ( usb_strings ) / sizeof ( const char * ) , usbd_control_buffer , sizeof ( usbd_control_buffer ) ) ;
usbd_register_set_config_callback ( usbd_dev , set_config ) ;
@ -540,7 +404,7 @@ void usbInit(void)
winusb_setup ( usbd_dev , USB_INTERFACE_INDEX_MAIN ) ;
}
void checkButtons ( void )
static void checkButtons ( void )
{
static bool btn_left = false , btn_right = false , btn_final = false ;
if ( btn_final ) {
@ -569,13 +433,13 @@ void checkButtons(void)
}
}
void usbLoop ( bool firmware_present )
void usbLoop ( void )
{
brand_new_firmware = ! firmware_present ;
bool firmware_present = firmware_present_new ( ) ;
usbInit ( ) ;
for ( ; ; ) {
usbd_poll ( usbd_dev ) ;
if ( brand_new_ firmware & & ( flash_state = = STATE_READY | | flash_state = = STATE_OPEN ) ) {
if ( ! firmware_present & & ( flash_state = = STATE_READY | | flash_state = = STATE_OPEN ) ) {
checkButtons ( ) ;
}
}